Java 8 스트림의 속성별 구별

Sheeraz Gul 2023년10월12일
  1. Java 8 스트림의 속성별 구별
  2. Collectors.toMap을 사용하여 Java에서 Distinct by Property 적용
  3. 래퍼 클래스를 사용하여 Java에서 Distinct by 속성 적용
  4. distinctByKey 메서드를 사용하여 Java에서 Distinct by 속성 적용
Java 8 스트림의 속성별 구별

이 자습서는 Java에서 스트림을 사용하여 속성별로 고유한 기능을 보여줍니다.

Java 8 스트림의 속성별 구별

Java 8 Stream에는 목록에서 중복 항목을 필터링하는 distinct() 메서드가 있습니다. 이 방법은 인스턴스의 equal 메서드를 사용하여 고유한 요소를 확인하고 중복된 항목이 있으면 제거합니다.

특정 속성이나 필드에 적용해야 하는 경우 distinct() 메서드를 사용할 수 없습니다. 그러나 특정 방법을 사용하여 속성별로 distinct() 메서드를 적용할 수 있습니다.

직원의 이름과 ID가 있는 Employee 클래스를 만든 다음 Employee 클래스 목록의 스트림에서 distinct() 메서드를 사용하는 예제를 시도해 보겠습니다.

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);
  }
}

위의 코드는 스트림을 사용하는 Employee 클래스 목록에서 distinct() 메서드를 사용하고 동일한 값을 가진 항목을 삭제합니다. 이 코드는 distinct() 메소드의 간단한 사용을 보여줍니다.

이제 Java에서 속성별로 고유한 논리를 적용하는 방법을 살펴보겠습니다.

Collectors.toMap을 사용하여 Java에서 Distinct by Property 적용

Collectors.toMap을 사용하여 스트림의 요소를 속성 또는 필드로 키를 지정할 맵으로 수집할 수 있습니다. 맵은 하나의 키에 대해 하나의 값만 가질 수 있으므로 각 키에 대해 첫 번째 스트림 객체를 선택해야 합니다.

결과 맵에서 values()를 호출할 수 있습니다. 이 맵은 고유한 논리를 적용하고 그룹화한 사용자 지정 속성별로 고유한 값을 제공합니다. 예를 보자:

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);
  }
}

위의 코드는 Employee_Name 속성을 기반으로 Collection.toMap 메서드를 사용하여 스트림에 고유한 논리를 적용합니다. 즉, 코드는 고유한 직원 이름이 있는 목록을 반환합니다. 출력 참조:

[Jake 50, Logan 60, Robert 40, John 20, Sheeraz 10]

보시다시피 Employee 목록에는 Sheeraz라는 이름을 가진 두 개의 항목이 있으며 그 중 하나는 이름 속성을 기반으로 구별을 적용했기 때문에 삭제됩니다.

래퍼 클래스를 사용하여 Java에서 Distinct by 속성 적용

래퍼 클래스를 생성하고 Employee 클래스에 속성을 할당한 다음 래퍼 클래스의 속성별로 distinct() 메서드를 적용할 수도 있습니다. 래퍼 클래스는 전용 정적이며 드라이버 클래스에서 선언됩니다.

예를 참조하십시오:

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);
  }
}

위의 코드는 스트림의 distinct() 메서드와 함께 래퍼 클래스 EmployeeWrapper를 사용하여 고유한 이름을 가진 직원 목록을 가져옵니다. 래퍼 클래스에서 equals() 메서드에 속성 이름을 할당한 다음 드라이버 클래스에서 사용하는 것을 볼 수 있습니다.

출력을 참조하십시오.

Sheeraz 10
John 20
Robert 40
Jake 50
Logan 60

distinctByKey 메서드를 사용하여 Java에서 Distinct by 속성 적용

이 방법에서는 동일한 값을 가진 기존 키가 있는지 확인하기 위해 동시 해시 맵을 사용해야 합니다. 이 메소드는 드라이버 클래스에서 선언된 다음 filter() 메소드와 함께 스트림에서 사용됩니다.

예를 참조하십시오.

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);
  }
}

위의 코드는 이름과 다시 이름과 ID를 기반으로 고유한 요소를 가져오려고 시도합니다. 출력을 참조하십시오.

[Sheeraz 10, John 20, Robert 40, Jake 50, Logan 60]
[Sheeraz 10, John 20, Sheeraz 30, Robert 40, Jake 50, Logan 60]

보시다시피 첫 번째 목록은 name 속성으로만 구분되고 두 번째 목록은 name 및 ID 속성으로 구분됩니다.

작가: Sheeraz Gul
Sheeraz Gul avatar Sheeraz Gul avatar

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

관련 문장 - Java Stream