본문 바로가기
Java

[Java] - Stream API ③ distinct()로 중복 요소 제거하기

by 개발 고양이 2025. 2. 18.

distinct() 메서드란?

 distinct() 메서드 스트림 API에서 제공하는 메서드 중 하나로, 컬렉션의 요소에서 중복을 제거한다. 

 

distinct()는 이전의 filter() 메서드와 같이, Stream API의 3단계 (Stream 생성 → 중간 연산 → 최종 연산) 중에서 중간 연산에 속한다. 따라서 이후에 최종 연산을 수행해야 distinct() 연산이 실제로 수행된다.

 

distinct() 메서드의 특징

1. Stream<T> 에서 중복된 요소를 제거하여 새로운 Stream 객체로 반환한다. 

=> 중복인지 아닌지 판단할 때 내부적으로 equals() 메서드를 사용한다.

 

2. 정렬 순서가 보존된다.

=> 원본 스트림의 순서를 유지하면서 중복을 제거한다. 중복 요소가 있을 경우 중복된 첫 번째 위치의 요소를 리턴한다.


distinct() 메서드 사용 예시

 

1. 정수형 리스트에서 중복 제거하기

import java.util.ArrayList;
import java.util.List;

public class Main {
	public static void main(String[] args) {
		List.of(1, 2, 2, 3, 4, 5, 5, 6).stream() // Stream 객체 생성
    		.distinct() // 중간 연산: distsinct()메서드로 중복 제거
    		.forEach(System.out::println); // 최종 연산: forEach() 메서드로 출력
    }
}

 

참고

중복 제거 연산 결과를 스트림 형태가 아닌 List로 받고 싶은 경우 아래와 같이 Collectors를 사용한다.

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

public class Main {
	public static void main(String[] args) {
		List.of(1, 2, 2, 3, 4, 5, 5, 6).stream() // Stream 객체 생성
    		.distinct() // 중간 연산: distsinct()메서드로 중복 제거
    		.collect(Collectors.toList()) // 스트림을 List로 변환
    		.forEach(System.out::println); // 최종 연산: forEach() 메서드로 출력
    }
}

2. 정렬되지 않은 문자열 리스트 중복 제거하기

import java.util.ArrayList;
import java.util.List;

public class Main {
	public static void main(String[] args) {
		List.of("b", "b", "c", "e", "a", "b", "a", "d").stream() // Stream 객체 생성
    		.distinct() // 중간 연산: distsinct()메서드로 중복 제거
    		.forEach(System.out::println); // 최종 연산: forEach() 메서드로 출력
    }
}

실행 결과 중복된 문자열만 제거되었고, 기존의 리스트 요소들의 순서가 보존된 것을 확인할 수 있다!

 

 


주의할 점

사용자가 정의한 클래스를 이용한 객체 리스트에서 중복을 제거하는 경우,

distinct()를 사용할 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;

    public 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 name + " (" + age + ")";
    }
}

public class Main {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Alice", 25), // 중복
                new Person("Charlie", 35)
        );

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

        System.out.println(distinctPeople);
        // 출력: [Alice (25), Bob (30), Charlie (35)]
    }
}