2009-11-03 18 views
13

simple pregunta.comparar dos listas de actualizaciones, supresiones y adiciones

Tengo una nueva lista y una lista anterior. En Java hay una manera/biblioteca estándar que me permite comparar estos dos listas y determinar qué elementos se han actualizado/borrado, o son completamente nuevos? P.ej. Debería terminar con tres listas - Elementos eliminados (artículos en edad, pero no en la nueva), artículos actualizados (artículos en ambos), nuevos artículos (artículos en nueva y no en edad).

Podría escribir esto yo mismo, pero me preguntaba si existe una forma estándar de hacerlo.

Los objetos en la lista del implemento son iguales.

+0

¿Le preocupa el orden de la lista? Por ejemplo, las soluciones sugeridas hasta ahora que incluyen retainAll/removeAll no tratarán la situación en la que la nueva lista contiene los mismos elementos que la lista anterior, aunque en un orden diferente; p.ej. {"foo", "bar"} vs {"bar", "foo"}. – Adamski

+0

Siempre que el método equals esté implementado correccional, no veo por qué el orden debería afectar removeAll, etc. Ciertamente no sugiere en el javadoc: Elimina de esta lista todos los elementos que están contenidos en la colección especificada (operación opcional). – Pablojim

Respuesta

31

No hay una norma camino lo siento. Puede hacerlo con bastante facilidad con JDK estándar sin tener que recurrir a la adición de una dependencia de Apache Commons (como han sugerido otros), sin embargo. Suponiendo que sus listas se List<T> casos:

List<T> oldList = ... 
List<T> newList= ... 

List<T> removed = new ArrayList<T>(oldList); 
removed.removeAll(newList); 

List<T> same = new ArrayList<T>(oldList); 
same.retainAll(newList); 

List<T> added = new ArrayList<T>(newList); 
added.removeAll(oldList); 
+0

+1 - sí, mucho mejor que el mío. –

+1

Lamentablemente, esto es un poco incorrecto ... removeAll y similares operan en la lista pasada y devuelven un booleano. Entonces eso no compilará. Debe ser: List added = new ArrayList (newList); added.removeAll (oldList); etc ... Así que podría haber un caso para los métodos de apache commons después de todo ... – Pablojim

+0

@Pablojim: de acuerdo, gracias. Fijo. – cletus

3

Usaría Apache CollectionUtils y usaría la unión (elementos en ambos) y las funciones de disyunción (cambie el orden para obtener una u otra).

Idealmente, haría una pasada sobre todos los elementos en lugar de 3, pero si este no es su cuello de botella, no me preocuparía la eficiencia en este momento.

7

No hay nada en las bibliotecas estándar.

Sin embargo, la clase CollectionUtils Apache Commons le ofrece esta funcionalidad con la intersección y restar métodos:

Collection<T> old = ...; 
Collection<T> neww = ...; 

Collection<T> deleted = (Collection<T>)CollectionUtils.subtract(old, new); 
Collection<T> updated = (Collection<T>)CollectionUtils.intersection(old, new); 
Collection<T> newResult = (Collection<T>)CollectionUtils.subtract(new, old); 

(Se necesita el (sin marcar) arroja porque CollectionUtils no se generified.)

1

Creo que se puede lograr esto con la biblioteca estándar de Java también. Echar un vistazo a los siguientes métodos de java.util.Collection:

retainAll (Collection c)

conserva solamente los elementos de esta colección que están contenidos en la colección especificada (opcional operación ) . En otras palabras, elimina de esta colección todos sus elementos que no están contenidos en la colección especificada .

removeAll (Collection c)

Elimina todos los elementos de esta recolección de que también están contenidos en el colección especificada (operación opcional ). Después de que regrese esta llamada, esta colección no contendrá elementos en común con la colección especificada.

0

Si hay una forma estándar, no sé que ...
Miré a Collections pero sólo vio disjuntos() (que es ya una información ...) y indexOfSubList() (no estoy seguro si es útil en absoluto).
I, también vieron Google Collections y si hay, al parecer, no instalación de ese tipo, hay algunas herramientas útiles allí, como función Collections2 's filtro() que puede ayudar si usted hace un predicado adecuado.

[EDIT] Me perdí los métodos removeAll y retainAll de colección ... No Eliminar esta respuesta, aunque un poco penoso, ya que de alguna manera es complementaria de las otras respuestas ... (creo que Google Colecciones es al menos vale la pena mencionar!)

2

Personalmente, creo que la única manera sensata de explicar la diferencia entre dos listas es con un algoritmo de diferencia en tiempo real (como el del comando diff unix).

Conjuntos, sin embargo, son una historia mucho más simple. Google Collections proporciona un método Sets.difference(Set, Set), además de unión e intersección.

Cuestiones relacionadas