クラスAの選択した「取得」メソッドをクラスBのメソッドに渡そうとしています。チェックアウトしたのは Javaパスメソッドをパラメーターとして ですが、インターフェースアプローチを採用できませんでした合理的な方法で私の問題。私はしないJava 8(lambdas)を使用し、可能であれば反射も回避することをお勧めします。私の気持ちは、私が自分の問題を間違った方法で見ていることをここに示します。
いくつかのフィールドとgetメソッドを含むクラスがあります。
_public class DataStore {
private float a;
private float b;
private float c;
public float getA() {
return a;
}
public float getB() {
return b;
}
public float getC() {
return c;
}
}
_
次に、マップの値としてDataStore
をインスタンス化してから、次のようにDataStoreの特定のフィールドにアクセスするメインクラスがあります。
_public class App {
public static void main(String[] args) {
// declare TreeMap using DataStore class as value
Map<Integer, DataStore> dataMap = new TreeMap<Integer, DataStore>();
// populate Map with example data
dataMap.put(2, new DataStore(1f,2f,3f));
dataMap.put(10, new DataStore(3f,4f,5f));
dataMap.put(4, new DataStore(6f,7f,8f));
// work with specific fields in DataStore, e.g. assign to array
float[] aArray = getValuesAsArray(dataMap, DataStore.getA());
float[] bArray = getValuesAsArray(dataMap, DataStore.getB());
float[] cArray = getValuesAsArray(dataMap, DataStore.getC());
}
/**
* Assign specific field of DataStore from Map to Array
* @param dataMap
* @param getVar - reference for specified getter method
* @return
*/
private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, MethodReference getVar()) {
int i = 0;
int nMap = dataMap.size();
float[] fArray = new float[nMap];
for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
DataStore ds = entry.getValue();
fArray[i] = ds.getVar();
i++;
}
return fArray;
}
}
_
選択したgetメソッドをgetValuesAsArray()
に渡す方法を理解する必要があるため、これは明らかに機能しません。どういうわけか、私のアプローチは間違っているかもしれません。だから私は提案を開いています。
getX()
メソッドは、DataStoreインスタンスを受け入れ、floatを返す関数と見なすことができます。
Java 8では、それらをメソッド参照で表すことができます。
_ float[] aArray = getValuesAsArray(dataMap, DataStore::getA);
float[] bArray = getValuesAsArray(dataMap, DataStore::getB);
float[] cArray = getValuesAsArray(dataMap, DataStore::getC);
_
次に、getValuesAsArray
は_Function<DataStore,Float>
_パラメータを受け入れ、関数を実行します。
_private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, Function<DataStore,Float> func) {
int i = 0;
int nMap = dataMap.size();
float[] fArray = new float[nMap];
for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
DataStore ds = entry.getValue();
fArray[i] = func.apply(ds);
i++;
}
return fArray;
}
_
Java 8を使用せずに、DataStore
インスタンスを受け入れ、float
を返すメソッドを含む独自のインターフェースを定義できます。次に、=を使用する代わりにJava 8つのメソッド参照。getValuesAsArray
メソッドに、getX()
の1つを呼び出すそのインターフェースの実装(インターフェースを実装する匿名クラスインスタンスを使用できます)を渡す必要があります。メソッド。
例えば :
_public interface ValueGetter
{
public float get (DataStore source);
}
float[] aArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getA();}});
float[] bArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getB();}});
float[] cArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getC();}});
_
そして
_private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, ValueGetter func) {
int i = 0;
int nMap = dataMap.size();
float[] fArray = new float[nMap];
for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
DataStore ds = entry.getValue();
fArray[i] = func.get(ds);
i++;
}
return fArray;
}
_
少し前にJava.util.concurrent.Callableを使用しましたが、@ Eranのおかげでうまくいかないようです。
代わりに、Java 8's Java.util.function.Function
を次のように使用できます(ラムダなし):
public static void main(String[] args) {
//...
getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getA(); }});
getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getB(); }});
getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getC(); }});
}
private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, Function<DataStore, Float> function) {
int i = 0;
int nMap = dataMap.size();
float[] fArray = new float[nMap];
for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
DataStore ds = entry.getValue();
fArray[i] = function.apply(ds);
i++;
}
return fArray;
}
MethodReference
はリフレクション用のクラスです。実際には、コードにはラムダのようなオブジェクトが必要です。これは、Java 8。
Java 8またはリフレクションなしでは、直接あなたのニーズを満たす方法はありません。しかし、メソッドの内部表現を別のクラスにいつでも渡すことができます。そうするためには、次のコードを書く必要があります。この内部表現を処理します。
回避策があります:Scala Java apis。
私はApacheを使用しますSparkおよびscalaは、Java 1.5以降で利用可能な一連の匿名関数(Function、Function2)を提供します) 、私が間違っていない場合(ただし、Java 1.7で使用します)。
これはこれについて話す答えです 。それ以外の場合、「関数」クラスはJava 1.8からのみ利用できます。