使用ComparisonChain而不是Objects.equal()&& Objects.equal()...与番石榴

时间:2011-08-04 13:15:39

标签: java equals guava comparisonchain

我刚开始使用google的Guava集合(ComparisonChainObjects)。在我的pojo中,我覆盖了equals方法,所以我先做了这个:

return ComparisonChain.start()
         .compare(this.id, other.id)
         .result() == 0;

然而,我意识到我也可以使用它:

return Objects.equal(this.id, other.id);

我没有看到比较链何时更好,因为你可以轻松地添加更多条件:

return Objects.equal(this.name, other.name) 
       && Objects.equal(this.number, other.number);

如果您特别需要返回int,我可以看到的唯一好处。它有两个额外的方法调用(开始和结果),并且对于菜鸟来说更复杂。

我错过了 ComparisonChain 的明显好处吗?

(是的,我也用适当的Objects.hashcode()覆盖哈希码)

4 个答案:

答案 0 :(得分:18)

ComparisonChain允许您通过比较多个属性(例如按多列排序网格)来检查对象是否小于或大于另一个对象。
在实施ComparableComparator

时应该使用它

Objects.equal只能检查是否相等。

答案 1 :(得分:11)

ComparisonChain旨在用于帮助对象实现Comparable或Comparator接口。

如果您只是实现Object.equals(),那么您是正确的; Objects.equal就是您所需要的。但是,如果您正在尝试实现Comparable或Comparator,那么使用ComparisonChain比使用其他方法更容易。

考虑:

class Foo implements Comparable<Foo> {
   final String field1;
   final int field2;
   final String field3;

   public boolean equals(@Nullable Object o) {
      if (o instanceof Foo) {
         Foo other = (Foo) o;
         return Objects.equal(field1, other.field1)
             && field2 == other.field2
             && Objects.equal(field3, other.field3);
      }
      return false;
   }

   public int compareTo(Foo other) {
      return ComparisonChain.start()
         .compare(field1, other.field1)
         .compare(field2, other.field2)
         .compare(field3, other.field3)
         .result();
   }
 }

而不是将compareTo实现为

 int result = field1.compareTo(other.field2);
 if (result == 0) {
   result = Ints.compare(field2, other.field2);
 }
 if (result == 0) {
   result = field3.compareTo(other.field3);
 }
 return result;

...更不用说正确地做到这一点的诡计,这比你猜想的要高。 (我已经看到了比你想象的更多比较混乱的方法。)

答案 2 :(得分:2)

在POJO中覆盖方法的上下文中,我想到了一些与几种标准方法匹配的Guava工具。

  • Object.equals使用Objects.equals按照您提到的方式处理
  • Object.hashCodeObjects.hashCode处理,如return Objects.hashCode(id, name);
  • Comparable.compareToComparisonChain处理,如下所示:

    public int compareTo(Chimpsky chimpsky) {
        return ComparisonChain.start()
            .compare(this.getId(), chimpsky.getId())
            .compare(this.getName(), chimpsky.getName())
            .result();
    }
    

答案 3 :(得分:0)

使用番石榴的ComparisonChain时要小心,因为它会为每个被比较的元素创建一个实例,因此您将查看N x Log N比较链的创建,以比较是否要排序,或N个实例(如果您要迭代并检查是否相等)。

如果可能的话,我会使用最新的Java 8 API或使用允许您执行此操作的Guava的Comparator API创建静态Ordering,这是Java 8的示例:

import java.util.Comparator;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;

private static final Comparator<DomainObject> COMPARATOR=Comparator
  .comparingInt(DomainObject::getId)
  .thenComparing(DomainObject::getName,nullsLast(naturalOrder()));

@Override
public int compareTo(@NotNull DomainObject other) {
  return COMPARATOR.compare(this,other);
}

以下是如何使用番石榴的Ordering API:https://github.com/google/guava/wiki/OrderingExplained