Powiedziałbym, że te odpowiedzi pomijają sztuczkę.
Bloch w swojej podstawowej, cudownej, zwięzłej Efektywnej Javie , mówi w pozycji 47, zatytułowanej „Poznaj i używaj bibliotek”, „Podsumowując, nie odkrywaj na nowo koła”. I podaje kilka bardzo wyraźnych powodów, dla których nie.
Jest tutaj kilka odpowiedzi, które sugerują metody z CollectionUtils
biblioteki Apache Commons Collections, ale żadna nie znalazła najpiękniejszego, najbardziej eleganckiego sposobu odpowiedzi na to pytanie :
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
}
Winowajcy : tj. Elementy, które nie są wspólne dla obu Lists
. Określenie, do kogo należą, list1
a do kogo winowajcy, list2
jest stosunkowo proste przy użyciu CollectionUtils.intersection( list1, culprits )
i CollectionUtils.intersection( list2, culprits )
.
Jednak ma tendencję do rozpadania się w przypadkach takich jak {"a", "a", "b"} disjunction
z {"a", "b", "b"} ... z wyjątkiem tego, że nie jest to awaria oprogramowania, ale nieodłączne od charakteru subtelności / niejasności pożądanego zadania.
Zawsze możesz sprawdzić kod źródłowy (l. 287) dla takiego zadania, jak to zostało stworzone przez inżynierów Apache. Jedną z korzyści płynących z używania ich kodu jest to, że został on gruntownie wypróbowany i przetestowany, z wieloma skrajnymi przypadkami i problemami przewidzianymi i rozwiązanymi. W razie potrzeby możesz skopiować i ulepszyć ten kod według własnego uznania.
Uwaga: Na początku byłem rozczarowany, że żadna z CollectionUtils
metod nie zapewnia przeładowanej wersji, umożliwiającej narzucenie własnej Comparator
(dzięki czemu można przedefiniować equals
ją tak, aby odpowiadała Twoim celom).
Ale z kolekcji4 4.0 jest nowa klasa, Equator
która „określa równość między obiektami typu T”. Podczas badania kodu źródłowego collections4 CollectionUtils.java wydaje się, że używają tego z niektórymi metodami, ale o ile wiem, nie ma to zastosowania do metod znajdujących się na początku pliku, przy użyciu CardinalityHelper
klasy ... która obejmują disjunction
i intersection
.
Przypuszczam, że ludzie z Apache jeszcze do tego nie doszli, ponieważ jest to nietrywialne: należałoby utworzyć coś w rodzaju klasy „AbstractEquatingCollection”, która zamiast używać elementów equals
i hashCode
metod jej elementów , musiałaby zamiast tego używać tych z Equator
dla wszystkich podstawowych metod, takich jak add
, contains
itp. Uwaga: w rzeczywistości, gdy patrzysz na kod źródłowy, AbstractCollection
nie implementuje add
, ani jego abstrakcyjnych podklas, takich jak AbstractSet
... musisz poczekać, aż konkretne klasy takie jak HashSet
i ArrayList
wcześniej add
jest zaimplementowane. Dość ból głowy.
Przypuszczam, że w międzyczasie obserwuj tę przestrzeń. Oczywistym tymczasowym rozwiązaniem byłoby umieszczenie wszystkich elementów w specjalnie zaprojektowanej klasie opakowania, która używa equals
i hashCode
zaimplementuje taki rodzaj równości, jaki chcesz, a następnie manipulowanie Collections
tymi obiektami opakowania.