Я бы сказал, что эти ответы упускают один трюк.
Блох в своей замечательной и краткой « Эффективной 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
этими объектами-оболочками.