Разница между 2 списками объектов в Java

#java #list #collections

#java #Список #Коллекции

Вопрос:

У меня есть тип obj MyObj следующим образом:

   class MyObj{
    String id;
    String username;
    String fullName;
    String age;

    //getters amp; setters
}
  

Предположим, у нас есть 2 списка, содержащих разное количество элементов, например:

 List<MyObj> listA
List<MyObj> listB
  

У меня есть общий метод, который обнаруживает элементы listA , отсутствующие в listB :

  public static <T> List<T> getListDifference(List<T> list1, List<T> list2) {
        Collection<T> first = new HashSet<T>(list1);
        Collection<T> second = new HashSet<T>(list2);
        first.removeAll(second);
        return new ArrayList<T>(first);
    }
  

Если объекты из listA и listB имеют одинаковые поля для всех элементов, все работает просто отлично.

Проблема в том, что некоторые элементы имеют только id и username , но другие могут иметь fullName или age тоже, и в результате этот метод больше не работает. Я бы хотел сохранить ту же логику, учитывая только id поле, потому что оно присутствует во всех объектах.

Одним из очевидных методов является копирование только id поля объекта в other List<String> и работа с полученными списками для обнаружения элементов, а затем просто поиск obj из обоих списков id . Этот метод имеет большую сложность из-за нескольких итераций. Есть ли короткий способ добиться этого?

Комментарии:

1. переопределить MyObj#equals и MyObj#hashCode

2. Я думаю, что вопрос вообще не связан с Android.

Ответ №1:

Как упоминал @ Kevin Esche, вы должны реализовать equals() and hashCode() в вашем MyObj POJO, и в зависимости от вашей ситуации они должны быть:

    @Override
public int hashCode() {
    return Objects.hash(id);
}

@Override
public boolean equals(Object obj) {
    if (obj == this) return true;
    if (!(obj instanceof MyObj)) return false;

    MyObj myObj= (MyObj) obj;
    return Objects.equals(id, myObj.id);
}
  

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

Комментарии:

1. if (!(obj instanceof MyObj)) должно быть заменено на if (obj == null || obj.getClass() != getClass()) . Потому что, если два объекта данных имеют разный класс, они, очевидно, не идентичны.

Ответ №2:

переопределить equals метод MyObjs:

 @Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    MyObj myObj = (MyObj) o;

    return (id != null ? !id.equals(myObj.id) : myObj.id != null);
}
  

В IntelliJ / Android Studio есть помощники для автоматической генерации equals и hashCode где вы можете выбрать необходимые свойства.

Ответ №3:

Вы должны реализовать equals и hashCode работать с наборами. Наборам нужен способ распознавания, равен ли один объект другому, и поведение по умолчанию здесь не сработает.

Кстати, я предлагаю использовать retainAll метод в списке, проверьте это.