Я бы сказал, что эти ответы упускают один трюк.
Блох в своей замечательной и краткой « Эффективной Java» в пункте 47, озаглавленном «Знайте и используйте библиотеки», говорит: «Подводя итог, не изобретайте велосипед». И он приводит несколько очень понятных причин, почему нет.
Здесь есть несколько ответов, которые предлагают методы из CollectionUtilsбиблиотеки Apache Commons Collections, но ни один из них не нашел наиболее красивого и элегантного способа ответа на этот вопрос :
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"} ... за исключением того, что это не сбой программного обеспечения, а присущие природе тонкости / неоднозначности желаемой задачи.
Вы всегда можете проверить исходный код (l. 287) для подобной задачи, созданный инженерами Apache. Одно из преимуществ использования их кода состоит в том, что он будет тщательно опробован и протестирован, с ожидаемыми и устраненными множеством крайних случаев и ошибок. Вы можете скопировать и настроить этот код по своему усмотрению, если потребуется.
NB. Сначала я был разочарован тем, что ни один из CollectionUtilsметодов не предоставляет перегруженную версию, позволяющую вам навязывать свою собственную Comparator(чтобы вы могли переопределить equalsв соответствии со своими целями).
Но из collections4 4.0 появился новый класс, Equatorкоторый «определяет равенство между объектами типа T». При изучении исходного кода collections4 CollectionUtils.java они, похоже, используют это с некоторыми методами, но, насколько я могу понять, это не применимо к методам в верхней части файла, использующим CardinalityHelperкласс ... который включить disjunctionи intersection.
Я предполагаю , что люди , Apache не удосужились это еще и потому , что это нетривиально: вы должны создать что - то вроде класса «AbstractEquatingCollection», который вместо того , чтобы использовать присущие его элементы equalsи hashCodeметоды вместо этого должен использовать те of Equatorдля всех основных методов, таких как add, containsи т. д. NB на самом деле, когда вы смотрите на исходный код, AbstractCollectionне реализует и не реализует addсвои абстрактные подклассы, такие как AbstractSet..., вам нужно дождаться, пока конкретные классы, такие как HashSetи ArrayListдо addреализовано. Довольно головная боль.
А пока, полагаю, понаблюдайте за этим пространством. Очевидным промежуточным решением было бы обернуть все ваши элементы в специальный класс-оболочку, который использует equalsи hashCodeреализует тот вид равенства, который вы хотите ... затем манипулируйте Collectionsэтими объектами-оболочками.