valores una posiciones matriz matrices elementos con comparar como caracteres cadena arreglos arreglo array java arrays list java-8 equals

posiciones - comparar valores de una matriz en java



¿Cómo comparar la igualdad de listas de matrices con Java moderno? (5)

Tengo dos listas de matrices.

¿Cómo puedo comparar fácilmente la igualdad de estos con Java 8 y sus características , sin usar bibliotecas externas? Estoy buscando una solución "mejor" (nivel superior, más corta, más eficiente) que el código de fuerza bruta como este (código no probado, puede contener errores tipográficos, etc., no es el punto de la pregunta):

boolean compare(List<String[]> list1, List<String[]> list2) { // tests for nulls etc omitted if(list1.size() != list2.size()) { return false; } for(i=0; i<list1.size(); ++i) { if(!Arrays.equals(list1.get(i), list2.get(i))) { return false; } } return true; }

O, si no hay una mejor manera, esa es una respuesta válida también.

Bonificación: si Java 9 ofrece una forma aún mejor de lo que Java 8 puede ofrecer, no dude en mencionarlo también.

Editar: después de mirar los comentarios y ver cómo esta pregunta se ha vuelto moderadamente candente, creo que lo " mejor " debería incluir primero verificar las longitudes de todas las matrices, antes de verificar el contenido de la matriz , porque eso tiene el potencial de encontrar la desigualdad mucho más rápido, si es interna Las matrices son largas.


El bucle for al menos se puede simplificar, lo que lleva a:

return (list1.size()==list2.size() && IntStream.range(0, list1.size()) .allMatch(i -> Arrays.equals(list1.get(i), list2.get(i)));


Puede transmitir en una lista y comparar con cada elemento de la otra mediante un iterador:

Iterator<String[]> it = list1.iterator(); boolean match = list1.size() == list2.size() && list2.stream().allMatch(a -> Arrays.equals(a, it.next()));

Usar un iterador en lugar del método get(index) en la primera lista es mejor porque no importa si la lista es RandomAccess o no.

Nota: esto solo funciona con una secuencia secuencial. El uso de un flujo paralelo conducirá a resultados incorrectos.

EDITAR: Según la última edición de la pregunta, que indica que sería mejor verificar la longitud de cada par de matrices por adelantado , creo que podría lograrse con una ligera modificación a mi código anterior:

Iterator<String[]> itLength = list1.iterator(); Iterator<String[]> itContents = list1.iterator(); boolean match = list1.size() == list2.size() && list2.stream() .allMatch(a -> { String[] s = itLength.next(); return s == null ? a == null : a == null ? s == null : a.length == s.length; }) && list2.stream() .allMatch(a -> Arrays.equals(a, itContents.next()));

Aquí estoy usando dos iteradores y estoy transmitiendo la list2 dos veces, pero no veo otra forma de verificar todas las longitudes antes de verificar el contenido del primer par de matrices. La verificación de longitudes es segura para nulos, mientras que la verificación de contenido se delega al Arrays.equals(array1, array2) .


Puede usar una secuencia si las listas son listas de acceso aleatorio (de modo que una llamada para get es rápida, generalmente tiempo constante) que conduce a:

//checks for null and size before boolean same = IntStream.range(0, list1.size()).allMatch(i -> Arrays.equals(list1.get(i), list2.get(i)));

Sin embargo, puede dar como parámetros algunas implementaciones que no lo son (como LinkedLists). En este caso, la mejor manera es usar el iterador explícitamente. Algo como:

boolean compare(List<String[]> list1, List<String[]> list2) { //checks for null and size Iterator<String[]> iteList1 = list1.iterator(); Iterator<String[]> iteList2 = list2.iterator(); while(iteList1.hasNext()) { if(!Arrays.equals(iteList1.next(), iteList2.next())) { return false; } } return true; }


usando la función zip (que se origina en lambda b93) de https://.com/a/23529010/755183 , el código podría verse así:

boolean match = a.size() == b.size() && zip(a.stream(), b.stream(), Arrays::deepEquals). allMatch(equal -> equal)

actualizar

Para verificar primero el tamaño de las matrices y luego el contenido, esta podría ser una solución a considerar

final boolean match = a.size() == b.size() && zip(a.stream(), b.stream(), (as, bs) -> as.length == bs.length). allMatch(equal -> equal) && zip(a.stream(), b.stream(), Arrays::deepEquals). allMatch(equal -> equal);


1) Solución basada en flujos de Java 8:

List<List<String>> first = list1.stream().map(Arrays::asList).collect(toList()); List<List<String>> second = list2.stream().map(Arrays::asList).collect(toList()); return first.equals(second);

2) Solución mucho más simple (funciona en Java 5+):

return Arrays.deepEquals(list1.toArray(), list2.toArray());

3) Con respecto a su nuevo requisito (para verificar primero la longitud de las matrices de cadenas contenidas), puede escribir un método auxiliar genérico que verifique la igualdad para las listas transformadas:

<T, U> boolean equal(List<T> list1, List<T> list2, Function<T, U> mapper) { List<U> first = list1.stream().map(mapper).collect(toList()); List<U> second = list2.stream().map(mapper).collect(toList()); return first.equals(second); }

Entonces la solución podría ser:

return equal(list1, list2, s -> s.length) && equal(list1, list2, Arrays::asList);