Как я могу проверить, отличаются ли два ArrayList, мне все равно, что изменилось - PullRequest
37 голосов
/ 07 июня 2010

Как я могу проверить, отличаются ли два списка ArrayList друг от друга? Мне все равно, в чем разница, я просто хочу знать, если они не одинаковы.

Я получаю список результатов из базы данных каждую минуту, и только если список результатов, который я выбрал, отличается от списка, который я выбрал минуту назад, я хочу отправить его клиенту.

Теперь значение ArrayList - это фактически класс, который я создал (который содержит имя, уровень, ранг, оценку).

Нужно ли реализовать equals() на нем?

Ответы [ 6 ]

79 голосов
/ 07 июня 2010

Об определении "одинаковости"

Как отметил Иоахим, для большинства приложений определение List.equals(Object o) работает:

Сравнивает указанный объект сэтот список на равенство.Возвращает true тогда и только тогда, когда указанный объект также является списком, оба списка имеют одинаковый размер, и все соответствующие пары элементов в двух списках равны.(Два элемента e1 и e2 равны, если (e1==null ? e2==null : e1.equals(e2)).) Другими словами, два списка определяются как равные, если они содержат одинаковые элементы в одинаковом порядке.Это определение гарантирует, что метод equals работает должным образом в различных реализациях интерфейса List.

Однако, в зависимости от того, как вы его используете, он может работать не так, как ожидалось.Например, если у вас есть List<int[]>, он не совсем работает, потому что массивы наследуют equals от Object, который определяет равенство в качестве ссылочного идентификатора.

    List<int[]> list1 = Arrays.asList(new int[] { 1, 2, 3 });
    List<int[]> list2 = Arrays.asList(new int[] { 1, 2, 3 });
    System.out.println(list1.equals(list2)); // prints "false"

Кроме того, два списка различного типапараметр может быть equals:

    List<Number> list1 = new ArrayList<Number>();
    List<String> list2 = new ArrayList<String>();
    System.out.println(list1.equals(list2)); // prints "true"

Вы также упомянули, что список должен содержать элементы того же типа.Вот еще один пример, где элементы не имеют одинаковый тип, и все же они equals:

    List<Object> list1 = new ArrayList<Object>();
    List<Object> list2 = new ArrayList<Object>();
    list1.add(new ArrayList<Integer>());
    list2.add(new LinkedList<String>());
    System.out.println(list1.equals(list2)); // prints "true"

Так что, если вы не определите, что для вас означает равенство, вопрос может иметь очень разныеответы.Однако для большинства практических целей вполне достаточно List.equals.


При реализации equals

Информация после обновления говорит о том, что List.equals отлично справится с работой, при условии , что элементы правильно реализуют equals (потому что List<E>.equals вызывает E.equals для не null -элементов согласно документации API выше).

Так что в этом случае,если у нас есть, скажем, List<Player>, то Player должен @Override equals(Object o) вернуть true, если o instanceof Player и в соответствующих полях, они все equals (для ссылочных типов) или ==(для примитивов).

Конечно, когда вы @Override equals, вы должны также @Override int hashCode().Едва приемлемый минимум составляет return 42;;немного лучше - до return name.hashCode();;Лучше всего использовать формулу, которая включает все поля, в которых вы определяете equals.Хорошая среда разработки может автоматически генерировать equals/hashCode методы для вас.

См. Также

  • Effective Java 2nd Edition
    • Элемент8: Соблюдайте общий контракт, если переопределение равно
    • Пункт 9: Всегда переопределять хэш-код, когда переопределение равно

APIссылки

Смежные вопросы

Вкл. equals/hashCode Комбо:

Вкл. equals против ==:

11 голосов
/ 07 июня 2010

Используйте equals(). Пока элементы в списках правильно реализуют equals(), он будет возвращать правильные значения.

Если вы не хотите игнорировать порядок значений, вы должны вывести значения в два Set объекта и сравнить их, используя equals().

8 голосов
/ 22 января 2017

Вот простой метод, который проверяет, содержат ли 2 массива одинаковые значения независимо от их порядка.

 //the name of the method explains it well...
    public boolean isTwoArrayListsWithSameValues(ArrayList<Object> list1, ArrayList<Object> list2)
    {
        //null checking
        if(list1==null && list2==null)
            return true;
        if((list1 == null && list2 != null) || (list1 != null && list2 == null))
            return false;

        if(list1.size()!=list2.size())
            return false;
        for(Object itemList1: list1)
        {
            if(!list2.contains(itemList1))
                return false;
        }

        return true;
    }
2 голосов
/ 02 января 2018

Вы можете преобразовать их в строку, а затем сравнить как

list1.toString().equals(list2.toString())
2 голосов
/ 23 августа 2015

Как отметил @Joachim Sauer в своем ответе, equals должно работать, если списки равны, а их содержимое реализует равно. Но он не должен работать, если элементы не в том же «порядке», так как он не использует содержимое для проверки. В этом смысле он проверяет «строгое» равенство, упомянутое @ jarnbjo

        //From android's Arraylist implementation
        Iterator<?> it = that.iterator();
        for (int i = 0; i < s; i++) {
            Object eThis = a[i];
            Object eThat = it.next();
            if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
                return false;
            }
        }

Однако я хотел немного другого поведения, меня не волновал порядок или что-то в этом роде. Все, что я хотел, это убедиться, что они не содержат одинаковые предметы. Мое решение,

    //first check that both are not null and are of same length. (not shown here)
    //if both match, pull out the big guns as below
    ...
    List<Object> comparedList = new ArrayList<>(listOne);
    comparedList.removeAll(listTwo);
    if(comparedList.size() != 0) //there are differences between the two

Это менее производительно, поскольку оно повторяется дважды, сначала в removeAll, а затем в contains, которое вызывается removeAll.

Мой список гарантированно был коротким, поэтому я не возражал против попадания.

0 голосов
/ 05 марта 2014

Вы также можете проверить Arraylist, как показано ниже:

public  boolean equalLists(List<String> one, List<String> two){     
if (one == null && two == null){
    return true;
}

if((one == null && two != null) 
  || one != null && two == null
  || one.size() != two.size()){
    return false;
}

//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one); 
two = new ArrayList<String>(two);   

Collections.sort(one);
Collections.sort(two);      
return one.equals(two);
}

Благодаря @ Джейкобу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...