此代码用于对List进行排序。该列表可以包含数千个但不到10k的元素。
protected <E> int compareFields(E o1, E o2, String fieldName){
try {
Comparable o1Data = (Comparable) o1.getClass().getMethod(fieldName).invoke(o1);
Comparable o2Data = (Comparable) o2.getClass().getMethod(fieldName).invoke(o2);
return o1Data == null ? o2Data == null ? 0 : 1 :
o2Data == null ? -1 : o1Data.compareTo(o2Data);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
我被建议
“请不要对这样的事情使用反射!! 要么使用合适的比较器提供方法,要么提取相关属性的方法(可能以原始类型不支持的方式计算),或两者兼而有之。“
更好的方法就是一个例子。
上下文: 我有很多带数据表的屏幕。每个都是从List构建的。每个数据表需要按其6列中的每一列进行排序。列是Date或String。
答案 0 :(得分:5)
在这里使用反射可能会慢得多,因为您使用getClass
,getMethod
和invoke
为每次比较添加了多个堆栈帧,而不是使用对象的本机比较方法
理想情况下,您可以编写方法以避免在签名中使用object
。 “合适的比较器”至少会强烈绑定到对象的类型(您假设它们是相同的)。如果必须进行动态字段比较(如图所示),那么至少可以将反射封装在该比较器中。
但是,如果要打几次这样的话,最好将比较器预先绑定到要排序的字段。这样,您只需预先调用getMethod
,而不是每次比较一次。
答案 1 :(得分:1)
如果没有上下文,很难给出一个很好的例子,所以现在这里列出了为什么它不是最好的想法的小清单:
答案 2 :(得分:1)
其他答案描述了为什么不建议使用反射。我想使用更传统的解决方案添加一个示例。
您应该将Comparator
实例作为参数,而不是指定用于比较两个对象的字段。这样,使用此方法的客户端可以指定如何比较两个对象。
protected <E> int compareFields(E o1, E o2, Comparator<E> comparator) {
return comparator.compare(o1, o2);
}
对此函数的示例调用如下所示:
MyClass a = ...;
MyClass b = ...;
Comparator<MyClass> intFieldComparator = new Comparator<MyClass> {
public int compare(MyClass o1, MyClass o2) {
int field1 = o1.getIntField();
int field2 = o2.getIntField();
return field2 - field1;
}
};
compareFields(a, b, intFieldComparator);
如果要使用多个字段比较对象,可以定义不同的比较器。