Distinto por propiedad en Java 8 Stream
- Distinto por propiedad en Java 8 Stream
-
Use
Collectors.toMap
para aplicar Distinct by Property en Java - Use una clase contenedora para aplicar Distinct by Property en Java
-
Use el método
distinctByKey
para aplicar Distinct by Property en Java
Este tutorial demuestra la funcionalidad distintiva por propiedad usando la secuencia en Java.
Distinto por propiedad en Java 8 Stream
Java 8 Stream tiene un método distinct()
que filtra los duplicados de una lista. Este método utiliza el método equal de la instancia para verificar los elementos únicos y, si ve duplicados, eliminarlos.
No podemos usar el método distinct()
si se requiere aplicarlo en una determinada propiedad o campo. Pero podemos aplicar el método distinct()
por propiedad usando una forma particular.
Probemos un ejemplo en el que creamos una clase Empleado
que tiene el nombre y la identificación del empleado y luego tratamos de usar el método distinct()
en la secuencia en la lista de clases Empleado
:
package delftstack;
import java.util.List;
import java.util.Objects;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static void main(String[] args) {
List<Employee> Employee_List =
List.of(new Employee("Sheeraz", 10), new Employee("John", 20), new Employee("Sheeraz", 30),
new Employee("Robert", 40), new Employee("Jake", 50), new Employee("Logan", 60));
// the distinct() will remove the duplicates by equals
Employee_List.stream().distinct().forEach(System.out::println);
}
}
El código de arriba usará el método distinct()
en una lista de clases de Empleados
usando la secuencia y eliminará las entradas con los mismos valores. El código muestra el uso simple del método distinct()
.
Ahora, veamos cómo aplicar una lógica distinta por propiedad en Java.
Use Collectors.toMap
para aplicar Distinct by Property en Java
Podemos usar Collectors.toMap
para recopilar los elementos de un flujo en un mapa para que la propiedad o el campo lo introduzcan. El mapa solo puede tener un valor para una clave, por lo que debemos elegir el primer objeto de flujo para cada clave.
Podemos llamar a los valores ()
del mapa resultante, que aplica la lógica distinta y nos da los valores únicos por una propiedad personalizada que agrupamos. Veamos un ejemplo:
package delftstack;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static void main(String[] args) {
List<Employee> Employee_List =
List.of(new Employee("Sheeraz", 10), new Employee("John", 20), new Employee("Sheeraz", 30),
new Employee("Robert", 40), new Employee("Jake", 50), new Employee("Logan", 60));
Collection<Employee> Unique_EmployeeList =
Employee_List.stream()
.collect(Collectors.toMap(
Employee::getName, Function.identity(), (Employee1, Employee2) -> Employee1))
.values();
System.out.println(Unique_EmployeeList);
}
}
El código anterior aplicará la lógica distinta en la secuencia utilizando el método Collection.toMap
basado en la propiedad Employee_Name
, lo que significa que el código devolverá una lista con nombres de empleados únicos. Ver salida:
[Jake 50, Logan 60, Robert 40, John 20, Sheeraz 10]
Como podemos ver, la lista de Empleados
tiene dos entradas con el nombre Sheeraz
, y una de ellas se elimina porque aplicamos una propiedad distinta basada en el nombre.
Use una clase contenedora para aplicar Distinct by Property en Java
También podemos crear una clase contenedora, asignar propiedades a la clase Empleado
y luego aplicar el método distinct()
por propiedad de la clase contenedora. La clase contenedora será estática privada y se declarará en la clase de controlador.
Ver ejemplo:
package delftstack;
import java.util.List;
import java.util.Objects;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
private static class EmployeeWrapper {
private Employee Employee;
private EmployeeWrapper(Employee Employee) {
this.Employee = Employee;
}
public Employee getEmployee() {
return Employee;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
EmployeeWrapper other = (EmployeeWrapper) Demo_Object;
return Objects.equals(Employee.getName(), other.Employee.getName());
}
@Override
public int hashCode() {
return Objects.hash(Employee.getName());
}
}
public static void main(String[] args) {
List<Employee> Employee_List =
List.of(new Employee("Sheeraz", 10), new Employee("John", 20), new Employee("Sheeraz", 30),
new Employee("Robert", 40), new Employee("Jake", 50), new Employee("Logan", 60));
Employee_List.stream()
.map(EmployeeWrapper::new)
.distinct()
.map(EmployeeWrapper::getEmployee)
.forEach(System.out::println);
}
}
El código anterior usa la clase contenedora EmployeeWrapper
con el método distinct()
de la secuencia para obtener la lista de empleados con nombres únicos. Podemos ver que en la clase contenedora, hemos asignado el nombre de la propiedad en el método equals()
, y luego lo usamos en la clase controladora.
Ver la salida:
Sheeraz 10
John 20
Robert 40
Jake 50
Logan 60
Use el método distinctByKey
para aplicar Distinct by Property en Java
En este método, tenemos que usar el mapa hash concurrente para averiguar si existe alguna clave con el mismo valor. Este método se declarará en la clase de controlador y luego se usará en la transmisión con el método filter()
.
Ver el ejemplo:
package delftstack;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> Key_Extractor) {
Map<Object, Boolean> Employee_Map = new ConcurrentHashMap<>();
return t -> Employee_Map.putIfAbsent(Key_Extractor.apply(t), Boolean.TRUE) == null;
}
public static void main(String[] args) {
List<Employee> Employee_List =
List.of(new Employee("Sheeraz", 10), new Employee("John", 20), new Employee("Sheeraz", 30),
new Employee("Robert", 40), new Employee("Jake", 50), new Employee("Logan", 60));
// Get distinct objects by one key
List<Employee> Distinct_Employees1 =
Employee_List.stream().filter(distinctByKey(p -> p.getName())).collect(Collectors.toList());
System.out.println(Distinct_Employees1);
// Get distinct objects by one key
List<Employee> Distinct_Employees2 =
Employee_List.stream()
.filter(distinctByKey(p -> p.getName() + " " + p.getID()))
.collect(Collectors.toList());
System.out.println(Distinct_Employees2);
}
}
El código anterior intenta obtener los distintos elementos en función del nombre y, nuevamente, el nombre y la identificación. Ver la salida:
[Sheeraz 10, John 20, Robert 40, Jake 50, Logan 60]
[Sheeraz 10, John 20, Sheeraz 30, Robert 40, Jake 50, Logan 60]
Como podemos ver, la primera lista se distingue solo por la propiedad de nombre, y la segunda se distingue por las propiedades de nombre e ID.
Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.
LinkedIn Facebook