问题描述
class DataObject
{
String attr1;
String attr2;
String attr3;
// getters of three fields(getAttr1(),getAttr2() and getAttr3())
// setters of three fields(setAttr1(),setAttr2() and setAttr3())
}
List<DataObject> result = null;//Output List of objects of 'DataObject' class
List<DataObject> dataObjectList; // Input List of objects of 'DataObject'class.
Predicate<DataObject> first= e -> e.getAttr1().equals("Value1_1");
result = dataObjectList.stream().filter(first).collect(Collectors.toList());
我想根据运行时的条件过滤对象列表(这里的条件是attr1 ="Value1_1").我的问题是,我只能在运行时获得方法名称(可以是getAttr1()或getAttr2()或getAttr3()或任何其他函数).我用反射来解决这种情况.
I want to filter my list of objects based on the conditions at runtime(Here condition is attr1 = "Value1_1"). My problem is that I will get the method name only in run time(It can be getAttr1() or getAttr2() or getAttr3() or any other function). I used reflection to solve this scenario.
Class<?> cls = Class.forName("com.example.java.DataObject");
Class<?> noparams[] = {};
Method method = cls.getDeclaredMethod("getAttr1", noparams);
Predicate<DataObject> first= e -> method.equals("Value1_1");
但是代码不会提供所需的结果.请在反射时更正我的代码.另外,请给我其他解决方案.
But the code will not give the required result. Please correct my code on reflection. Also please give me any alternative solutions.
推荐答案
您是否对使用反射进行此设置不满意?反思常常带来的麻烦多于其价值.怎么样:
Are you dead-set on doing this with reflection? Reflection is often more trouble than it's worth. How about this:
class DataObject {
static enum Attr {
Attr1(DataObject::getAttr1),
Attr2(DataObject::getAttr2),
Attr3(DataObject::getAttr3),
Attr4(DataObject::getAttr4);
final Function<DataObject, Object> getter;
Attr(Function<DataObject, Object> getter) {
this.getter = requireNonNull(getter);
}
}
// .... rest of the class ....
}
Attr attribute = Attr.valueOf("Attr1");
List<DataObject> filtered = dataObjectList.stream()
.filter(e -> "Value_1".equals(attribute.getter.apply(e)))
.collect(toList());
显然,缺点是您必须为每个属性添加一个枚举值.但是好处在于简单性和能够通过类型安全的枚举而不是字符串来引用属性的能力.获取有效属性(Attr.values()
)的列表也将非常容易.
Obviously, the downside is that you would have to add an enum value for every attribute. But the upside is simplicity and the ability to refer to your attributes by type-safe enum rather than by strings. It will also be very easy to get a list of valid attributes (Attr.values()
).
设置好之后,您可以做一些有趣的事情,例如在enum
中添加以下内容:
Once you set that up, you can do fun things like adding the following to your enum
:
<T> Predicate<DataObject> matches(Predicate<T> p) {
return e -> p.test((T)getter.apply(e));
}
然后您就可以像这样编写代码:
And then you'll be able to write your code like this:
Attr attribute = Attr.valueOf("Attr1");
List<DataObject> filtered = dataObjectList.stream()
.filter(attribute.matches("Value_1"::equals))
.collect(toList());
这篇关于Java中带有反射的谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!