#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
метод в списке, проверьте это.