【问题标题】:Comparator vs Apache BeanComparator比较器与 Apache BeanComparator
【发布时间】:2012-07-11 21:16:05
【问题描述】:

考虑一个简单的类:

class Employee {

String name;
int sal;

....//getters and setters
}

例如,我可以创建一个比较器来对字段名称进行排序。

class EmpSortByName implements Comparator<Employee>{

 @Override
 public int compare(Employee e1, Employee e2){
  return e1.getName().compareTo(e2.getName());
 }
}

但是,查看 apache commons BeanComparator,排序可以通过以下方式实现:

BeanComparator bc = new BeanComparator("name");
Collections.sort(employeeList, bc);

因此,通过使用 BeanComparator,我可以用最少的代码实现排序。使用 Comparator 和 BeanComparator 之间的权衡是什么:在性能、使用场景(多字段排序、其他因素)方面?

我也知道要使用 BeanComparator,必须导入 beanutils jar。

【问题讨论】:

  • 这是一个最小的“明显”代码。别忘了你不知道 BeanComparator 做了什么,而且性能可能不如第一种方法

标签: java performance apache comparison comparator


【解决方案1】:

BeanComparator 使用反射来访问 name 属性并比较两个对象。尽管反射性能有所提高,但仍不如直接访问字段快。这是否重要取决于在您的应用程序中调用它的次数,以及在何种上下文中。

另一个问题是,如果重构方法并将其重命名为getLastName(),则使用 BeanComparator 的代码将不会被重构,并且直到运行时(或单元测试时)才会注意到该问题。

坦率地说,实现比较器非常简单,我认为使用反射不是一个好主意。避免 4 行琐碎代码的好处并不足以弥补它导致的性能和可维护性问题。

【讨论】:

  • @JB 你是对的,由于反射会影响性能。什么情况下应该使用BeanComparator? “最小”代码是唯一的原因吗?你还能想到其他原因吗?
  • 我自己从来不需要使用它,但我可以想象在单元测试中使用它,或者当 UI 允许动态选择哪些属性对象必须进行排序时,或者在 JSP 标记中比如 displaytag,它必须在不知道它们的类型的情况下比较 bean,而不需要开发人员提供比较器
  • 在上述问题的上下文中,我同意这个解决方案,但是如果你必须对类的给定字段进行排序怎么办。如果类的字段太多,那么我们不能为每个字段编写一个比较器,因此应该使用 BeanComparator。
  • 如果没有反射和通用过滤我们的 JSF,Hibernate 企业应用程序将有一个更大的代码库来维护无限的特定 DAO、转换器、比较器、过滤器。 rename 参数是有效的,但我们希望有朝一日所有第三方库都支持 java lambda,使其过时。在 C# 堆栈中,无需字符串 bean 路径即可轻松传递动态谓词。例如 primefaces 惰性数据表为您提供了带有 bean 属性路径表示法的过滤器映射。如果您不想要样板代码,则必须使用反射。
【解决方案2】:

此外,使用 beancomparator,您可以使用 compareTuple 轻松比较多个属性 org.ujac.util.BeanComparator beanComparator = new org.ujac.util.BeanComparator(compareTuple); Collections.sort(List,beanComparator);

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 2010-11-14
    • 2012-04-06
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    相关资源
    最近更新 更多