我正在尝试将类A的选定“get”方法传递给B类中的方法。我已经检查了Java Pass Method as Parameter,但我无法采用接口方法解决我的问题。合理的方式。我更喜欢不使用java 8(lambdas),如果可能的话也避免反射。我的感觉是,我以错误的方式看待我的问题。 以下是我要完成的具体简化示例:
我有一个包含一些字段和get-methods的类:
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
实例化为Map的值,然后访问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()
。
不知怎的,我想,我的做法可能是错的。所以我愿意接受建议。
答案 0 :(得分:10)
您的getX()
方法可以看作是一个接受DataStore实例并返回浮点数的函数。
在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()
之一方法
例如:
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;
}
答案 1 :(得分:2)
前一段时间我使用了java.util.concurrent.Callable,但由于@Eran,它似乎无法解决。
相反,你可以使用Java 8的java.util.function.Function
,就像这样(没有lambdas):
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;
}
答案 2 :(得分:0)
MethodReference
是一个用于反思目的的类。您的代码实际上需要一个类似lambda的对象,它应该是Java 8中的单个方法接口。
如果没有Java 8或反射,就无法直接满足您的需求。但是你总是可以将方法的一些内部表示传递给另一个calss,为此你必须编写代码来处理这个内部表示。
答案 3 :(得分:0)
有一种解决方法:Scala java apis。
我使用Apache Spark,scala提供了一系列自Java 1.5以来可用的匿名函数(函数,函数2),如果我没有弄错的话(尽管我在Java 1.7中使用它)。
Here is an answer talking about this。因为“Function”类只能从Java 1.8中获得
答案 4 :(得分:-1)