12

我刚刚开始使用 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,我可以看到的唯一好处。它有两个额外的方法调用(开始和结果),对于菜鸟来说更复杂。

我缺少的比较链有明显的好处吗?

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

4

4 回答 4

22

ComparisonChain允许您通过比较多个属性(例如按多列对网格进行排序)来检查一个对象是小于还是大于另一个对象。
它应该在实现Comparable或时使用Comparator

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

于 2011-08-04T13:18:45.053 回答
13

比较链旨在帮助对象实现 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;

...更不用说正确地做到这一点的棘手了,这比你想象的要高。(我见过比你想象的更多搞砸 compareTo 的方法。)

于 2011-09-16T18:54:33.070 回答
2

在 POJO 中覆盖方法的上下文中,我认为 Guava 的一些工具与一些标准方法相匹配。

  • Object.equalsObjects.equals大致按照您提到的方式处理
  • Object.hashCodeObjects.hashCode像处理return Objects.hashCode(id, name);
  • Comparable.compareTo处理ComparisonChain如下:

    public int compareTo(Chimpsky chimpsky) {
        return ComparisonChain.start()
            .compare(this.getId(), chimpsky.getId())
            .compare(this.getName(), chimpsky.getName())
            .result();
    }
    
于 2011-08-04T13:57:17.853 回答
1

使用番石榴时我会小心,ComparisonChain因为它会为每个被比较的元素创建一个实例,因此您将查看N x Log N比较链的创建只是为了比较您是否正在排序,或者N如果您正在迭代和检查是否相等则实例。

如果可能的话,我会Comparator使用最新的 Java 8 API 或 Guava 的OrderingAPI 创建一个静态的,它允许你这样做,这里是一个 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);
}

以下是如何使用 Guava 的OrderingAPI:https ://github.com/google/guava/wiki/OrderingExplained

于 2018-11-15T10:52:18.980 回答