В чем преимущество использования ComparisonChain над Objects.equal () && Objects.equal () ... с Guava - PullRequest
10 голосов
/ 04 августа 2011

Я только что начал использовать коллекцию гуавы в Google ( ComparisonChain и Objects ).В моем 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 ]

18 голосов
/ 04 августа 2011

ComparisonChain позволяет проверить, является ли объект меньше или больше другого объекта путем сравнения нескольких свойств (например, сортировка сетки по нескольким столбцам). Его следует использовать при реализации Comparable или Comparator.

Objects.equal можно проверить только на равенство.

11 голосов
/ 16 сентября 2011

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 голосов
/ 04 августа 2011

В контексте переопределения методов в ваших POJO, я думаю о нескольких инструментах Guava, соответствующих нескольким стандартным методам.

  • Object.equals обрабатывается с использованием Objects.equals примерно такВы упомянули, что
  • Object.hashCode обрабатывается с Objects.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();
    }
    
0 голосов
/ 15 ноября 2018

Я был бы осторожен при использовании Guava's ComparisonChain, потому что он создает экземпляр этого для каждого сравниваемого элемента, поэтому вы будете смотреть на создание N x Log N цепочек сравнения просто для сравнения, если вы сортируете, или N случаи, если вы выполняете итерацию и проверяете равенство.

Вместо этого я бы создал статический Comparator с использованием новейшего API Java 8, если это возможно, или API Ordering Guava, который позволяет вам сделать это, вот пример с 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);
}

Вот как использовать API Ordering в Guava: https://github.com/google/guava/wiki/OrderingExplained

...