¿Cuál es la forma más sencilla de encontrar si dos Listas contienen exactamente los mismos elementos, en las bibliotecas estándar de Java?
No debería importar si las dos Listas son la misma instancia o no, y no debería importar si el parámetro de tipo de las Listas es diferente.
p.ej
List list1
List<String> list2;
// ... construct etc
list1.add("A");
list2.add("A");
// the function, given these two lists, should return true
Probablemente hay algo mirándome a la cara que sé :-)
EDITAR: Para aclarar, estaba buscando los mismos elementos EXACTOS y el número de elementos, en orden.
java
collections
Grundlefleck
fuente
fuente
Respuestas:
Si le importa el orden, simplemente use el método igual:
Desde el javadoc:
Si desea verificar independientemente del orden, puede copiar todos los elementos en Conjuntos y usar iguales en los Conjuntos resultantes:
Una limitación de este enfoque es que no solo ignora el orden, sino también la frecuencia de elementos duplicados. Por ejemplo, si
list1
fue ["A", "B", "A"] ylist2
fue ["A", "B", "B"], elSet
enfoque los consideraría iguales.Si necesita ser insensible al orden pero sensible a la frecuencia de los duplicados, puede:
fuente
a = [x, y, x]
yb = [x, y, z]
luego los tamaños son iguales yb.containsAll(a)
devolverán verdadero, perob
contiene un elemento que no está ena
.Publiqué un montón de cosas en los comentarios, creo que justifica su propia respuesta.
Como todos dicen aquí, usar equals () depende del orden. Si no le importa el orden, tiene 3 opciones.
Opción 1
Uso
containsAll()
. Esta opción no es ideal, en mi opinión, porque ofrece el peor rendimiento posible, O (n ^ 2).opcion 2
Hay dos variaciones a esto:
2a) Si no le importa mantener el orden de sus listas ... úselas
Collections.sort()
en ambas. Luego usa elequals()
. Esto es O (nlogn), porque haces dos tipos, y luego una comparación O (n).2b) Si necesita mantener el orden de las listas, puede copiar ambas listas primero. ENTONCES puede usar la solución 2a en ambas listas copiadas. Sin embargo, esto podría no ser atractivo si la copia es muy costosa.
Esto lleva a:
Opción 3
Si sus requisitos son los mismos que en la parte 2b , pero copiar es demasiado costoso. Puede usar un TreeSet para hacer la clasificación por usted. Volcar cada lista en su propio TreeSet. Se ordenará en el conjunto y las listas originales permanecerán intactas. Luego realice una
equals()
comparación en ambosTreeSet
s. ElTreeSets
s se puede construir en tiempo O (nlogn), yequals()
es O (n).Elige tu opción :-).
EDITAR: Casi olvido la misma advertencia queseñala Laurence Gonsalves . La implementación de TreeSet eliminará los duplicados. Si le interesan los duplicados, necesitará algún tipo de multiset ordenado.
fuente
a.containsAll(b) && b.containsAll(a)
Si está usando (o está contento de usar) Colecciones Apache Commons, puede usar CollectionUtils.isEqualCollection que "devuelve verdadero si las Colecciones dadas contienen exactamente los mismos elementos con exactamente las mismas cardinalidades".
fuente
Muy tarde a la fiesta, pero quería agregar este cheque seguro nulo:
fuente
Sé que este es un hilo viejo, pero ninguna de las otras respuestas resolvió por completo mi caso de uso (supongo que Guava Multiset podría hacer lo mismo, pero no hay ningún ejemplo aquí). Por favor disculpe mi formateo. Todavía soy nuevo en publicar en el intercambio de pila. Además, avíseme si hay algún error
Digamos que tiene
List<T>
una yList<T>
b y desea comprobar si son iguales, con las siguientes condiciones:1) O (n) tiempo de ejecución esperado
2) La igualdad se define como: Para todos los elementos en aob, el número de veces que el elemento ocurre en a es igual al número de veces que el elemento ocurre en b. La igualdad de elementos se define como T.equals ()
El tiempo de ejecución es O (n) porque estamos haciendo O (2 * n) inserciones en un hashmap y O (3 * n) selecciones de hashmap. No he probado completamente este código, así que ten cuidado :)
fuente
Pruebe esta versión que no requiere que el orden sea el mismo, pero admite tener múltiples del mismo valor. Solo coinciden si cada uno tiene la misma cantidad de cualquier valor.
fuente
El método igual en Lista hará esto, las listas están ordenadas, por lo que para ser iguales, dos listas deben tener los mismos elementos en el mismo orden.
fuente
Solución para el caso cuando dos listas tienen los mismos elementos, pero un orden diferente:
fuente
removeAll()
lugar decontainsAll()
(entiendo que si listTwo contiene duplicados que están contenidos solo una vez en listOne, el enfoque contieneTodo () informaría incorrectamente las listas como iguales).La respuesta de Tom es excelente. ¡Estoy totalmente de acuerdo con sus respuestas!
Un aspecto interesante de esta pregunta es si necesita el
List
tipo en sí y su ordenamiento inherente.De lo contrario, puede degradarse
Iterable
oCollection
le da cierta flexibilidad para pasar estructuras de datos que se ordenan en el momento de la inserción, en lugar de en el momento en que desea verificar.Si el orden nunca importa (y no tiene elementos duplicados) considere usar a
Set
.Si el orden importa pero está definido por el tiempo de inserción (y no tiene duplicados) considere uno
LinkedHashSet
que es como un TreeSet pero está ordenado por tiempo de inserción (los duplicados no se cuentan). Esto también le daO(1)
acceso amortizado en lugar deO(log n)
.fuente
Código de muestra:
fuente
Además de la respuesta de Laurence, si también desea que sea nulo seguro:
fuente
if (list1 == null) return list2==null; if (list2 == null) return false;
Si su lista contiene una clase personalizada MyClass, esta clase debe anular la
equals
función.Nota: si desea probar iguales en java.util.Set en lugar de a
java.util.List
, entonces su objeto debe anular lahashCode
función.fuente
List.equals ()
http://java.sun.com/j2se/1.5/docs/api/java/util/List.html#equals(java.lang.Object)
fuente
Puede usar la biblioteca org.apache.commons.collections de Apache: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html
fuente
Compruebe que ambas listas no son nulas. Si sus tamaños son diferentes, entonces estas listas no son iguales. Cree mapas que consten de los elementos de las listas como claves y sus repeticiones como valores y compare los mapas.
Suposiciones, si ambas listas son nulas, las considero iguales.
Tenga en cuenta que los métodos iguales deben definirse adecuadamente para estos objetos. https://stackoverflow.com/a/24814634/4587961
fuente
[x, x, y]
vs[x, y, y]
volvería a ser verdadero con tu implementación.Depende de qué clase de Lista concreta esté utilizando. La clase abstracta AbstractCollection tiene un método llamado contiene todo (Colección) que toma otra colección (una Lista es una colección) y:
Entonces, si se pasa una ArrayList, puede llamar a este método para ver si son exactamente iguales.
La razón de contieneTodo () es porque itera a través de la primera lista buscando la coincidencia en la segunda lista. Entonces, si están fuera de servicio, igual a () no lo recogerá.
EDITAR: Solo quiero hacer un comentario aquí sobre el tiempo de ejecución amortizado de realizar las diversas opciones que se ofrecen. ¿Es importante el tiempo de ejecución? Por supuesto. ¿Es lo único que debes considerar? No.
El costo de copiar CADA elemento individual de sus listas en otras listas lleva tiempo, y también ocupa una buena parte de la memoria (duplicando efectivamente la memoria que está utilizando).
Entonces, si la memoria en su JVM no es una preocupación (que generalmente debería serlo), entonces aún debe considerar el tiempo que lleva copiar cada elemento de dos listas en dos TreeSets. Recuerde que está ordenando cada elemento a medida que ingresa en ellos.
¿Mi último consejo? Debe considerar su conjunto de datos y cuántos elementos tiene en su conjunto de datos, y también qué tan grande es cada objeto en su conjunto de datos antes de poder tomar una buena decisión aquí. Juegue con ellos, cree uno en cada sentido y vea cuál corre más rápido. Es un buen ejercicio.
fuente