переопределить метод equals для сравнения более одного поля в Java - PullRequest
3 голосов
/ 18 августа 2011

Каков наилучший способ переопределить метод equals в java для сравнения нескольких полей? Например, у меня есть 4 объекта в классе, o1, o2, o3, o4, и я хочу сравнить их все с переданным объектом с методом equals.

if (o1 != null && o2 != null && o3 != null && o4 != null && obj.o1 != null
    && obj.o2 != null && obj.o3 != null && obj.o4 != null
    && o1.equals(obj.o1) && o2.equals(obj.o2) && o3.equals(obj.o3) && o4.equals(obj.o4)) {
    do something
}

Проблема с этим кодом в том, что он не понятен и не может быть легко изменен, особенно если у нас есть больше полей. Есть ли лучший способ добиться этого?

Ответы [ 6 ]

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

Дешевый способ будет сделать:

Arrays.asList(o1, o2, o3, o4).equals(Arrays.asList(obj.o1, obj.o2, obj.o3, obj.o4));
9 голосов
/ 18 августа 2011

Одна вещь - иметь вспомогательный метод в служебном классе:

public static boolean equals(Object o1, Object o2)
{
     if (o1 == o2)
     {
         return true;
     }
     if (o1 == null || o2 == null)
     {
         return false;
     }
     return o1.equals(o2);
}

Тогда вы можете написать:

public boolean equals(Object other)
{
    if (other == null || this.getClass() != other.getClass())
    {
        return false;
    }
    Foo x = (Foo) other;
    return Helper.equals(o1, x.o1) &&
           Helper.equals(o2, x.o2) &&
           Helper.equals(o3, x.o3) &&
           Helper.equals(o4, x.o4);
}

Обратите внимание, что таким образом он также справляется, когда два поля равны нулю, чего нет в коде в вопросе. (Я говорю «справляется» - это дает результат, который более соответствует остальной части Java.)

Вы можете создать аналогичный вспомогательный метод и для hashCode.

Обратите внимание, что Guava уже поддерживает это в своем классе Objects (и я уверен, что многие другие вспомогательные библиотеки тоже).

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

Использование Гуава :

@Override
public boolean equals(final Object obj){
    if (!(obj instanceof Foo)) {
        return false;
    }
    final Foo other = (Foo) obj;
    return Objects.equal(o1, other.o1)
        && Objects.equal(o2, other.o2)
        && Objects.equal(o3, other.o3)
        && Objects.equal(o4, other.o4);
}

Вы также получаете дешевый hashCode ():

@Override
public int hashCode() {
    return Objects.hashCode(o1, o2, o3, o4);
}
5 голосов
/ 18 августа 2011

Используйте служебный метод, чтобы помочь вам

private static boolean nullSafeEquals(Object o1, Object o2) {
    if(o1 == null && o2 == null) return true; // both null, both equal
    if(o1 == null || o2 == null) return false; // if one is null, not equal - we know both won't be null
    return o1.equals(o2);
}

public boolean equals(Object o) {
    if(o instanceof ThisClass) {
        ThisClass tc = (ThisClass)o;
        return nullSafeEquals(o1, tc.o1)
            && nullSafeEquals(o2, tc.o2)
            && nullSafeEquals(o3, tc.o3)
            && nullSafeEquals(o4, tc.o4);
    }
    return false;
}
0 голосов
/ 18 августа 2011

Я сталкивался с этим несколько раз, и самый простой способ сделать это - поместить все сравниваемые объекты в LinkedList, а затем написать метод сравнения для вашего объекта, который возьмет этот список и проведет его по узнайте, равны ли они переданному объекту. Вы можете даже обнаружить, что метод LinkedList 'contains ()' сделает это за вас, в зависимости от ваших объектов.

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

Если вы используете один из них, пусть создадут его для вас.

...