Tengo dos ArrayLists.
ArrayList A contiene:
['2009-05-18','2009-05-19','2009-05-21']
ArrayList B contiene:
['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']
Tengo que comparar ArrayList A y ArrayList B. El resultado ArrayList debe contener la Lista que no existe en ArrayList A.
El resultado de ArrayList debe ser:
['2009-05-20','2009-05-22']
como comparar
equals
que permita comparar sus objetos. Lea sobre la implementaciónhashCode
también. Por ejemplo, nota cómoString::equals
es entre mayúsculas y minúsculas , por lo que "Apple" y "Apple" no se considerará la misma.removeAll
invocafirstList.contains
todos los elementos desecondList
. Usar unHashSet
evitaría eso y hay algunas buenas respuestas más bajas.Ya tienes la respuesta correcta. Y si quieres hacer operaciones más complicadas e interesantes entre Listas (colecciones) usa apache commons collections ( CollectionUtils ) Te permite hacer conjucción / disyunción, encontrar intersección, comprobar si una colección es un subconjunto de otra y otras cosas agradables.
fuente
En Java 8 con streams, en realidad es bastante simple. EDITAR: Puede ser eficiente sin flujos, ver más abajo.
List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21"); List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19", "2009-05-20","2009-05-21","2009-05-21","2009-05-22"); List<String> result = listB.stream() .filter(not(new HashSet<>(listA)::contains)) .collect(Collectors.toList());
Tenga en cuenta que el conjunto de hash solo se crea una vez: la referencia del método está vinculada a su método contiene. Hacer lo mismo con lambda requeriría tener el conjunto en una variable. Hacer una variable no es una mala idea, especialmente si le resulta desagradable o más difícil de entender.
No puede negar fácilmente el predicado sin algo como este método de utilidad (o conversión explícita), ya que no puede llamar directamente a la referencia del método negado (primero se necesita la inferencia de tipo).
private static <T> Predicate<T> not(Predicate<T> predicate) { return predicate.negate(); }
Si las transmisiones tuvieran un
filterOut
método o algo, se vería mejor.Además, @Holger me dio una idea.
ArrayList
tiene suremoveAll
método optimizado para múltiples eliminaciones, solo reorganiza sus elementos una vez. Sin embargo, utiliza elcontains
método proporcionado por la colección dada, por lo que necesitamos optimizar esa parte silistA
es cualquier cosa menos pequeña.Con
listA
ylistB
declarado previamente, esta solución no necesita Java 8 y es muy eficiente.List<String> result = new ArrayList(listB); result.removeAll(new HashSet<>(listA));
fuente
Predicates.in(new HashSet<>(listA)).negate()
.ArrayList.remove
tiene complejidad lineal, peroArrayList.removeAll
no se basa enremove
una operación de actualización de matriz lineal, sino que la realiza, copiando cada elemento restante en su lugar final. Por el contrario, la implementación de referencia deLinkedList
no se ha optimizadoremoveAll
sino que realiza unaremove
operación para cada elemento afectado, que actualizará hasta cinco referencias cada vez. Por lo tanto, dependiendo de la proporción entre los elementos eliminados y los restantes, losArrayList
'sremoveAll
todavía pueden tener un rendimiento significativamente mejor que losLinkedList
' s, incluso para listas grandes.EDITAR: La pregunta original no especificó el idioma. Mi respuesta está en C #.
En su lugar, debería utilizar HashSet para este propósito. Si debe utilizar ArrayList, puede utilizar los siguientes métodos de extensión:
var a = arrayListA.Cast<DateTime>(); var b = arrayListB.Cast<DateTime>(); var c = b.Except(a); var arrayListC = new ArrayList(c.ToArray());
usando HashSet ...
var a = new HashSet<DateTime>(); // ...and fill it var b = new HashSet<DateTime>(); // ...and fill it b.ExceptWith(a); // removes from b items that are in a
fuente
He usado Guava Sets.difference .
Los parámetros son conjuntos y no colecciones generales, pero una forma práctica de crear conjuntos a partir de cualquier colección (con elementos únicos) es Guava ImmutableSet.copyOf (Iterable).
(Primero publiqué esto en una pregunta relacionada / dupe , pero también lo estoy copiando aquí porque creo que es una buena opción que hasta ahora falta).
fuente
Aunque esta es una pregunta muy antigua en Java 8, podría hacer algo como
List<String> a1 = Arrays.asList("2009-05-18", "2009-05-19", "2009-05-21"); List<String> a2 = Arrays.asList("2009-05-18", "2009-05-18", "2009-05-19", "2009-05-19", "2009-05-20", "2009-05-21","2009-05-21", "2009-05-22"); List<String> result = a2.stream().filter(elem -> !a1.contains(elem)).collect(Collectors.toList());
fuente
Collection
el método decontains
, es muy ineficiente. Debe pasar por toda la lista si no se encuentra. Hacerlo para cada elemento dea2
puede ser dolorosamente lento en listas más grandes, por lo que hago un conjuntoa1
en mi respuesta.Supongo que estás hablando de C #. Si es así, puedes probar esto
ArrayList CompareArrayList(ArrayList a, ArrayList b) { ArrayList output = new ArrayList(); for (int i = 0; i < a.Count; i++) { string str = (string)a[i]; if (!b.Contains(str)) { if(!output.Contains(str)) // check for dupes output.Add(str); } } return output; }
fuente
b
listaa.Count
. En su lugar, puede crear un métodoHashSet
para usarloContains
o usar elRemoveAll
método en el conjunto para obtener exactamente los resultados que desea.Solo estás comparando cadenas.
Coloque los valores en ArrayList A como claves en HashTable A.
Coloque los valores en ArrayList B como claves en HashTable B.
Luego, para cada clave en HashTable A, elimínela de HashTable B si existe.
Lo que le queda en HashTable B son las cadenas (claves) que no eran valores en ArrayList A.
Ejemplo de C # (3.0) agregado en respuesta a la solicitud de código:
List<string> listA = new List<string>{"2009-05-18","2009-05-19","2009-05-21'"}; List<string> listB = new List<string>{"2009-05-18","2009-05-18","2009-05-19","2009-05-19","2009-05-20","2009-05-21","2009-05-21","2009-05-22"}; HashSet<string> hashA = new HashSet<string>(); HashSet<string> hashB = new HashSet<string>(); foreach (string dateStrA in listA) hashA.Add(dateStrA); foreach (string dateStrB in listB) hashB.Add(dateStrB); foreach (string dateStrA in hashA) { if (hashB.Contains(dateStrA)) hashB.Remove(dateStrA); } List<string> result = hashB.ToList<string>();
fuente
hashA
variable es efectivamente inútil. En su lugar, podría hacer un foreachlistA
yahashA
que solo se itera yContains
nunca se llama.Hola, use esta clase, esto comparará ambas listas y muestra exactamente la falta de coincidencia en ambas listas.
import java.util.ArrayList; import java.util.List; public class ListCompare { /** * @param args */ public static void main(String[] args) { List<String> dbVinList; dbVinList = new ArrayList<String>(); List<String> ediVinList; ediVinList = new ArrayList<String>(); dbVinList.add("A"); dbVinList.add("B"); dbVinList.add("C"); dbVinList.add("D"); ediVinList.add("A"); ediVinList.add("C"); ediVinList.add("E"); ediVinList.add("F"); /*ediVinList.add("G"); ediVinList.add("H"); ediVinList.add("I"); ediVinList.add("J");*/ List<String> dbVinListClone = dbVinList; List<String> ediVinListClone = ediVinList; boolean flag; String mismatchVins = null; if(dbVinListClone.containsAll(ediVinListClone)){ flag = dbVinListClone.removeAll(ediVinListClone); if(flag){ mismatchVins = getMismatchVins(dbVinListClone); } }else{ flag = ediVinListClone.removeAll(dbVinListClone); if(flag){ mismatchVins = getMismatchVins(ediVinListClone); } } if(mismatchVins != null){ System.out.println("mismatch vins : "+mismatchVins); } } private static String getMismatchVins(List<String> mismatchList){ StringBuilder mismatchVins = new StringBuilder(); int i = 0; for(String mismatch : mismatchList){ i++; if(i < mismatchList.size() && i!=5){ mismatchVins.append(mismatch).append(","); }else{ mismatchVins.append(mismatch); } if(i==5){ break; } } String mismatch1; if(mismatchVins.length() > 100){ mismatch1 = mismatchVins.substring(0, 99); }else{ mismatch1 = mismatchVins.toString(); } return mismatch1; } }
fuente
ESTE TRABAJA TAMBIÉN CON Arraylist
// Create a couple ArrayList objects and populate them // with some delicious fruits. ArrayList<String> firstList = new ArrayList<String>() {/** * */ private static final long serialVersionUID = 1L; { add("apple"); add("orange"); add("pea"); }}; ArrayList<String> secondList = new ArrayList<String>() { /** * */ private static final long serialVersionUID = 1L; { add("apple"); add("orange"); add("banana"); add("strawberry"); }}; // Show the "before" lists System.out.println("First List: " + firstList); System.out.println("Second List: " + secondList); // Remove all elements in firstList from secondList secondList.removeAll(firstList); // Show the "after" list System.out.println("Result: " + secondList);
fuente
remove
ycontains
necesitan buscar en toda la lista. Si se llama repetidamente en un ciclo (lo que ocurre enremoveAll
), obtiene una complejidad cuadrática. Sin embargo, podría usar un conjunto de hash y hacerlo simplemente lineal.