repetidos recorrer objetos listas lista enlazadas comparar array java java-8 java-stream

recorrer - Fusionando dos Lista de objetos en java 8



listas java (4)

Por ejemplo:

public class Parent { public int no; public String name; @Override public int hashCode() { return (no << 4) ^ name.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Parent)) return false; Parent o = (Parent)obj; return this.no == o.no && this.name.equals(o.name); } }

Tengo un Java clase Parent con 20 atributos (attrib1, attrib2 .. attrib20) y sus getters y setters correspondientes. También tengo dos listas de objetos principales: list1 y list2 .

Ahora quiero fusionar ambas listas y evitar objetos duplicados basados ​​en attrib1 y attrib2 .

Usando Java 8:

List<Parent> result = Stream.concat(list1.stream(), list2.stream()) .distinct() .collect(Collectors.toList());

Pero, ¿en qué lugar debo especificar los atributos? ¿Debo anular hashCode e equals método?


Si desea implementar equals y hashCode , el lugar para hacerlo está dentro de la clase Parent . Dentro de esa clase agrega los métodos como

@Override public int hashCode() { return Objects.hash(getAttrib1(), getAttrib2(), getAttrib3(), // … getAttrib19(), getAttrib20()); } @Override public boolean equals(Object obj) { if(this==obj) return true; if(!(obj instanceof Parent)) return false; Parent p=(Parent) obj; return Objects.equals(getAttrib1(), p.getAttrib1()) && Objects.equals(getAttrib2(), p.getAttrib2()) && Objects.equals(getAttrib3(), p.getAttrib3()) // … && Objects.equals(getAttrib19(), p.getAttrib19()) && Objects.equals(getAttrib20(), p.getAttrib20()); }

Si hiciste esto, distinct() invocado en un Stream<Parent> automáticamente hará lo correcto.

Si no quiere (o no puede) cambiar la clase Parent , no existe un mecanismo de delegación para la igualdad, pero puede recurrir a ordenar ya que tiene un mecanismo de delegación:

Comparator<Parent> c=Comparator.comparing(Parent::getAttrib1) .thenComparing(Parent::getAttrib2) .thenComparing(Parent::getAttrib3) // … .thenComparing(Parent::getAttrib19) .thenComparing(Parent::getAttrib20);

Esto define un orden basado en las propiedades. Requiere que los tipos de los atributos en sí sean comparables. Si tiene esa definición, puede usarla para implementar el equivalente de distinct() , basado en ese Comparator :

List<Parent> result = Stream.concat(list1.stream(), list2.stream()) .filter(new TreeSet<>(c)::add) .collect(Collectors.toList());

También hay una variante segura para subprocesos, en caso de que quiera usarla con flujos paralelos:

List<Parent> result = Stream.concat(list1.stream(), list2.stream()) .filter(new ConcurrentSkipListSet<>(c)::add) .collect(Collectors.toList());


Si desea sobrescribir .equals(…) y .hashCode() , debe hacerlo en la clase Parent . Tenga en cuenta que esto puede causar que otros usos de Parent fallen. La solución vinculada de Alexis C. es más conservadora.


hashCode métodos equals y hashCode en la clase Parent para evitar duplicados de las listas. Esto le dará el resultado exacto de lo que quiere.