본문 바로가기
프로그래밍/JAVA

Java Streams API - 3

by 낭만프로그래머. 2024. 5. 26.

distinct의 사용 예제

다음은 distinct 메서드의 기본 사용 예제입니다.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
        
        List<Integer> distinctNumbers = numbers.stream()
                                               .distinct()
                                               .collect(Collectors.toList());
        
        System.out.println(distinctNumbers);  // 출력: [1, 2, 3, 4, 5]
    }
}

위의 예제에서 distinct 메서드는 리스트에서 중복된 숫자들을 제거하고, 고유한 숫자들로 이루어진 새로운 리스트를 반환합니다.

distinct의 내부 동작

distinct 메서드는 각 요소의 equals 메서드를 사용하여 중복을 판단합니다. 따라서 요소들이 equals와 hashCode 메서드를 올바르게 구현하고 있어야 합니다. 특히 사용자 정의 객체를 사용할 때는 equals와 hashCode 메서드를 잘 구현해야 합니다.

예제

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

public class DistinctExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("John", 25),
            new Person("John", 25),
            new Person("Jane", 30)
        );

        List<Person> distinctPeople = people.stream()
                                            .distinct()
                                            .collect(Collectors.toList());

        System.out.println(distinctPeople);  // 출력: [Person{name='John', age=25}, Person{name='Jane', age=30}]
    }
}

위의 예제에서 Person 클래스는 equals와 hashCode 메서드를 올바르게 구현하고 있습니다. 따라서 distinct 메서드는 중복된 Person 객체를 제거하고 고유한 객체들만 남깁니다.

distinct 와 성능

distinct 메서드는 내부적으로 요소들을 Set에 추가하여 중복을 제거합니다. 이 과정은 시간 복잡도가 O(n)으로, 요소의 개수에 비례하여 성능이 저하될 수 있습니다. 특히 스트림의 크기가 클 경우, distinct 연산이 성능에 영향을 미칠 수 있습니다.

병렬 스트림에서의 distinct

distinct 메서드는 병렬 스트림에서도 동일하게 동작하지만, 병렬 처리의 이점은 제한적일 수 있습니다. 병렬 스트림은 기본적으로 ForkJoinPool을 사용하여 작업을 분할 처리하지만, distinct 메서드는 모든 요소를 비교해야 하므로 병렬 처리의 이점을 충분히 누리기 어려울 수 있습니다.

병렬 스트림 예제:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
        
        List<Integer> distinctNumbers = numbers.parallelStream()
                                               .distinct()
                                               .collect(Collectors.toList());
        
        System.out.println(distinctNumbers);  // 출력: [1, 2, 3, 4, 5]
    }
}

위의 예제는 병렬 스트림에서 distinct를 사용하는 경우로, 결과는 순차 스트림과 동일합니다. 그러나 병렬 처리가 distinct 연산의 성능을 크게 향상시키지는 않습니다.

결론

distinct 메서드는 Java Streams API에서 중복 요소를 제거하는 데 사용되는 중간 연산입니다. 요소의 equals 메서드를 사용하여 중복을 판단하며, Set을 내부적으로 사용하여 고유한 요소들만 남깁니다. 사용자 정의 객체를 사용할 때는 equals와 hashCode 메서드를 올바르게 구현해야 합니다. distinct는 병렬 스트림에서도 사용할 수 있지만, 병렬 처리의 성능 이점은 제한적일 수 있습니다.

'프로그래밍 > JAVA' 카테고리의 다른 글

Java stream 의 Optional.orElseThrow  (0) 2024.07.28
Multi Datasource 를 이용한 database routing 전략  (0) 2024.07.06
Java Streams API - 2  (0) 2024.05.26
Java Streams API - 1  (0) 2024.05.26