2010-12-03 26 views
33

Tengo dos ArrayList<Integer> de la siguiente manera:intersección de lista en Java

el original: 12, 16, 17, 19, 101

seleccionados: 16, 19, 107, 108, 109

quiero hacer intersección/unión en estas listas de tal manera que al final tengo dos listas:

Añadir: 108,109,107

remove: 12, 17, 101

Longitud de listas originales y seleccionadas varía y uno puede ser mayor/menor que el otro

+0

Así que básicamente desea eliminar los valores que aparecen en ambas listas? ¿Las listas siempre están ordenadas como están en tu ejemplo? – Asaph

+3

Debería "Agregar:' 108,109' "ser" Agregar: '107,108,109'"? – Asaph

+1

No veo cómo cualquiera de estos es una unión O una intersección. La intersección sería '16, 19 ', p. Ej. –

Respuesta

35
List<Integer> original = Arrays.asList(12,16,17,19,101); 
List<Integer> selected = Arrays.asList(16,19,107,108,109); 

ArrayList<Integer> add = new ArrayList<Integer>(selected); 
add.removeAll(original); 
System.out.println("Add: " + add); 

ArrayList<Integer> remove = new ArrayList<Integer>(original); 
remove.removeAll(selected); 
System.out.println("Remove: " + remove); 

Salida:

Add: [107, 108, 109] 
Remove: [12, 17, 101] 

Utiliza el método de removeAll de colección. See javadocs.

+1

Tenga en cuenta que 'removeAll' quita _all_ occurances de cada valor - por lo que si '16' estuvo en' selected' dos veces, aún no estaría en el 'add' final . Por lo tanto, no es adecuado si necesita detectar duplicados (p.encontrar elementos faltantes, inesperados y duplicados en una lista). –

5
List<Integer> original; 
List<Integer> selected; 

List<Integer> add = new ArrayList<Integer>(selected); 
add.removeAll(original); 

List<Integer> remove = new ArrayList<Integer>(original); 
remove.removeAll(selected); 

que tener cuidado con los casos borde alrededor de los elementos duplicados. ¿Debería respetarse la cardinalidad? Como en, si tuviera 5, 6 originalmente y 5, 5, 6 después, ¿debería agregar 5? Lo anterior funciona mejor con Set s, ya que no tienen duplicados (más las búsquedas son más rápidas ya que están indexadas por los datos que contienen).

36

Como alternativa, puede usar CollectionUtils de la biblioteca de Apache commons. Tiene una intersección estática, unión y resta métodos adecuados para su caso.

+0

en mi opinión, esta debería haber sido la mejor respuesta. gracias :) – Tohid

+0

Desafortunadamente no es compatible con los genéricos de java :( – rafalmag

+1

lo hace en la versión 4: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html# intersección (java.lang.Iterable, java.lang.Iterable) – user829755

5

Para operaciones de intersección y unión, el tipo de colección natural es un conjunto en lugar de una lista, también es más eficiente de usar.

5

El uso de la biblioteca de guayaba:

List<Integer> listA = Lists.newArrayList(12,16,17,19,101); 
List<Integer> listB = Lists.newArrayList(16,19,107,108,109); 
Set<Integer> intersection = Sets.intersection(Sets.newHashSet(listA), Sets.newHashSet(listB)); 
listA.removeAll(intersection); 
listB.removeAll(intersection); 
+0

Guavas Sets.intersection es propenso a errores porque el segundo argumento es 'Set '. Puede pasar, por ejemplo, un 'Set ' y el compilador no se quejará. – user829755

15

Intersección: original.retainAll(selected).

Después de ese original contendrá solo los elementos presentes en ambas colecciones. Devuelve verdadero si algo cambió.

+1

Cierto, pero puede repetir elementos, por lo que no es estrictamente una Intersección. – kike

+1

@kike, si no desea repetir elementos, use un 'Conjunto' https://docs.oracle.com/javase/7/docs/api /java/util/Set.html#retainAll(java.util.Collection) – ACV

+0

El único problema con este enfoque parece un rendimiento deficiente – ACV

1

Hay una nueva biblioteca disponible underscore-java. Puede hacer diferencias e intersecciones para listas y matrices.

ejemplo Código:

List<Integer> original = asList(12, 16, 17, 19, 101); 
List<Integer> selected = asList(16, 19, 107, 108, 109); 
List<Integer> add = $.difference(selected, $.intersection(original, selected)); 
List<Integer> remove = $.difference(original, selected);