Yo diría que estas respuestas pierden un truco.
Bloch, en su esencial, maravilloso, conciso Java efectivo , dice, en el ítem 47, título "Conozca y use las bibliotecas", "Para resumir, no reinvente la rueda". Y da varias razones muy claras por las que no.
Aquí hay algunas respuestas que sugieren métodos de CollectionUtils
la biblioteca Apache Commons Collections, pero ninguna ha descubierto la forma más hermosa y elegante de responder esta pregunta :
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... do something with the culprits, i.e. elements which are not common
}
Culpables : es decir, los elementos que no son comunes a ambos Lists
. Determinar a qué culpables pertenece list1
y a qué list2
es relativamente sencillo usar CollectionUtils.intersection( list1, culprits )
y CollectionUtils.intersection( list2, culprits )
.
Sin embargo, tiende a desmoronarse en casos como {"a", "a", "b"}disjunction
con {"a", "b", "b"} ... excepto que esto no es una falla del software, pero inherente a la naturaleza de las sutilezas / ambigüedades de la tarea deseada.
Siempre puede examinar el código fuente (l. 287) para una tarea como esta, producida por los ingenieros de Apache. Una ventaja de usar su código es que habrá sido probado y probado exhaustivamente, con muchos casos extremos y problemas previstos y tratados. Puede copiar y ajustar este código al contenido de su corazón si es necesario.
Nota: Al principio me decepcionó que ninguno de los CollectionUtils
métodos proporciona una versión sobrecargada que le permite imponer la suya Comparator
(para que pueda redefinirla equals
según sus propósitos).
Pero de collections4 4.0 hay una nueva clase, Equator
que "determina la igualdad entre los objetos de tipo T". Al examinar el código fuente de collections4 CollectionUtils.java, parecen estar usando esto con algunos métodos, pero por lo que puedo entender, esto no es aplicable a los métodos en la parte superior del archivo, usando la CardinalityHelper
clase ... que incluir disjunction
y intersection
.
Supongo que la gente de Apache todavía no se ha dado cuenta de esto porque no es trivial: tendrías que crear algo así como una clase "AbstractEquatingCollection", que en lugar de usar los elementos equals
y hashCode
métodos inherentes a sus elementos, tendría que usar esos de Equator
todos los métodos básicos, como add
, contains
etc. NB, de hecho, cuando mira el código fuente, AbstractCollection
no implementa add
, ni sus subclases abstractas como AbstractSet
... tiene que esperar hasta las clases concretas como HashSet
y ArrayList
antes add
está implementado. Todo un dolor de cabeza.
Mientras tanto mira este espacio, supongo. La solución provisional obvia sería envolver todos sus elementos en una clase de envoltura a medida que utilice equals
e hashCode
implementar el tipo de igualdad que desee ... luego manipular Collections
estos objetos de envoltura.