Я б сказав, що ці відповіді пропускають хитрість.
Блох, у своїй важливій, чудовій, стислій Ефективній Java , у пункті 47 зазначає заголовок «Знай і користуйся бібліотеками», «Підсумувати, не винаходити колесо». І він наводить кілька дуже чітких причин, чому ні.
Тут є кілька відповідей, які пропонують методи з CollectionUtilsбібліотеки колекцій Apache Commons, але жоден не знайшов найкрасивішого, елегантного способу відповісти на це питання :
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... do something with the culprits, i.e. elements which are not common
}
Винуватці : тобто елементи, які не є спільними для обох Lists. Визначення, до яких винуватців належать, list1а до list2яких відносно просте використання CollectionUtils.intersection( list1, culprits )та CollectionUtils.intersection( list2, culprits ).
Однак вона, як правило, розпадається на випадки, як {"a", "a", "b"} disjunctionз {"a", "b", "b"} ... за винятком цього не є збоєм програмного забезпечення, але притаманні природі тонкощів / неоднозначності бажаного завдання.
Ви завжди можете вивчити вихідний код (л. 287) для подібного завдання, виробленого інженерами Apache. Однією з переваг використання їх коду є те, що він буде ретельно випробуваний і протестований, з багатьма крайніми справами та готчами передбачається і вирішується. Ви можете скопіювати і підкоригувати цей код до вмісту серця, якщо це буде потрібно.
NB: Спочатку я був розчарований, що жоден із CollectionUtilsметодів не забезпечує перевантажену версію, що дозволяє вам нав'язувати своє Comparator(щоб ви могли переосмислитись equalsвідповідно до своїх цілей).
Але з collection4 4.0 з'явився новий клас, Equatorякий "визначає рівність між об'єктами типу T". Перевіряючи вихідний код collection4 CollectionUtils.java, вони, здається, використовують це деякими методами, але, наскільки я можу це зробити, це не стосується методів у верхній частині файлу, використовуючи CardinalityHelperклас ... який включати disjunctionі intersection.
Я гадаю, що люди Apache ще не вирішили цього питання, оскільки це нетривіально: вам доведеться створити щось на кшталт класу "AbstractEquatingCollection", який замість того, щоб використовувати притаманні його елементи equalsта hashCodeметоди, замість цього повинен був би використовувати ці з Equatorусіх основних методів, таких як add, containsі т.д. NB насправді , коли ви подивіться на вихідний код, AbstractCollectionне реалізує add, ні робити свої абстрактні підкласи , такі як AbstractSet... ви повинні чекати , поки класи бетону , такі як HashSetі ArrayListдо того addреалізується. Досить болить голова.
Тим часом спостерігаю за цим простором, я думаю. Очевидним тимчасовим рішенням було б обернути всі ваші елементи в замовлений клас обгортки, який використовує equalsта hashCodeреалізувати потрібну рівність ... потім маніпулювати Collectionsцими об'єктами обгортки.