Мне нужно объединить все элементы listB в другой список listA.
Если элемент уже присутствует (на основе пользовательской проверки равенства) в listA, я не хочу его добавлять.
Я не хочу использовать Set, и я не хочу переопределять equals() и hashCode().
Причины: я не хочу предотвращать дубликаты в списке A как таковой, я только хочу не сливаться с listB, если уже есть элементы в списке A, которые я считаю равными.
Я не хочу переопределять equals() и hashCode(), поскольку это означало бы, что мне нужно убедиться, что моя реализация equals() для элементов имеет место в каждом случае. Однако может быть, что элементы из спискаB не полностью инициализированы, то есть они могут пропустить идентификатор объекта, где это может присутствовать в элементах списка A.
Мой текущий подход включает интерфейс и служебную функцию:
public interface HasEqualityFunction<T> {
public boolean hasEqualData(T other);
}
public class AppleVariety implements HasEqualityFunction<AppleVariety> {
private String manufacturerName;
private String varietyName;
@Override
public boolean hasEqualData(AppleVariety other) {
return (this.manufacturerName.equals(other.getManufacturerName())
&& this.varietyName.equals(other.getVarietyName()));
}
// ... getter-Methods here
}
public class CollectionUtils {
public static <T extends HasEqualityFunction> void merge(
List<T> listA,
List<T> listB) {
if (listB.isEmpty()) {
return;
}
Predicate<T> exists
= (T x) -> {
return listA.stream().noneMatch(
x::hasEqualData);
};
listA.addAll(listB.stream()
.filter(exists)
.collect(Collectors.toList())
);
}
}
И тогда я буду использовать его следующим образом:
...
List<AppleVariety> appleVarietiesFromOnePlace = ... init here with some elements
List<AppleVariety> appleVarietiesFromAnotherPlace = ... init here with some elements
CollectionUtils.merge(appleVarietiesFromOnePlace, appleVarietiesFromAnotherPlace);
...
чтобы получить мой новый список в списке A со всеми элементами, объединенными с B.
Это хороший подход? Есть ли лучший/более простой способ сделать то же самое?