¿Cuál es la mejor manera de obtener la diferencia simétrica entre dos conjuntos en Java?

Me pregunto si hay una forma rápida / limpia de obtener la diferencia entre dos conjuntos.

Yo tengo:

Set s1 = new HashSet(); s1.add("a"); s1.add("b"); s1.add("c"); Set s2 = new HashSet(); s2.add("b"); 

Necesito algo como:

 Set diff = Something.diff(s1, s2); // diff would contain ["a", "c"] 

Solo para aclarar, necesito la diferencia simétrica .

Puede usar algunas funciones de la biblioteca de Google Guava (¡que es realmente genial, lo recomiendo encarecidamente!):

 Sets.difference(s1, s2); Sets.symmetricDifference(s1, s2); 

Javadocs para difference () y symmetricDifference ()

symmetricDifference() difference() symmetricDifference() hace exactamente lo que estás pidiendo , pero la difference() también suele ser útil.

Ambos métodos devuelven una vista en vivo, pero puede, por ejemplo, llamar a .immutableCopy() en el conjunto resultante para obtener un conjunto que no cambie. Si no quiere una vista, pero necesita una instancia establecida que puede modificar, llame a .copyInto(s3) . Vea SetView para estos métodos.

Quieres la diferencia simétrica .

 public static  Set diff(final Set s1, final Set s2) { Set symmetricDiff = new HashSet(s1); symmetricDiff.addAll(s2); Set tmp = new HashSet(s1); tmp.retainAll(s2); symmetricDiff.removeAll(tmp); return symmetricDiff; } 

Si quieres una biblioteca, Apache Commons CollectionUtils tiene

 CollectionUtils.disjunction(s1, s2) 

que devuelve una Collection no genérica.

y Guava Sets tiene

 Sets.symmetricDifference(s1, s2) 

que devuelve un Set no modificable como Sets.SetView genérico.

La guayaba es un poco más moderna, admite generics, pero cualquiera de estos funcionará.

Si puede usar colecciones de Apache-Commons , está buscando CollectionUtils.disjunction(Collection a, Collection b) . Devuelve la diferencia simétrica de ambas Colecciones.

Si no, removeAll ( removeAll ) la intersección ( retainAll ) de ambos conjuntos a la unión de ambos ( addAll ):

 Set intersection = new HashSet(set1); intersection.retainAll(set2); Set difference = new HashSet(); difference.addAll(set1); difference.addAll(set2); difference.removeAll(intersection); 

Pasa por un conjunto y compara.

Es solo O(n) recorrer uno de los conjuntos. Considera este código:

 for (String key: oldSet) { if (newSet.contains(key)) newSet.remove(key); else newSet.add(key); } 

Y newSet contendrá ahora solo las entradas únicas de ambos conjuntos. Es rápido, porque solo necesita recorrer los elementos en uno de los conjuntos y no tiene que crear conjuntos a menos que necesite una copia explícitamente.

 public class Practice { public static void main(String[] args) { Set set1 = new HashSet(); Set set2 = new HashSet(); set1.add(1); set1.add(4); set1.add(7); set1.add(9); set2.add(2); set2.add(4); set2.add(5); set2.add(6); set2.add(7); symmetricSetDifference(set1, set2); } public static void symmetricSetDifference(Setset1, Setset2){ //creating a new set Set newSet = new HashSet(set1); newSet.removeAll(set2); set2.removeAll(set1); newSet.addAll(set2); System.out.println(newSet); } 

}

 s1.addAll(s2); s1.removeAll(s2); 

Deberia trabajar.