웹사이트 검색

중복을 제거하는 Java Stream distinct() 함수


Java Stream distinct() 메서드는 고유한 요소의 새 스트림을 반환합니다. 처리하기 전에 컬렉션에서 중복 요소를 제거하는 데 유용합니다.

자바 스트림 distinct() 메서드

  • 요소는 equals() 메서드의 적절한 구현이 있는 스트림 요소를 사용하여 비교됩니다.
  • 스트림이 정렬되면 발생 순서가 유지됩니다. 이는 먼저 발생하는 요소가 개별 요소 스트림에 존재함을 의미합니다.
  • 스트림이 정렬되지 않은 경우 결과 스트림 요소는 임의의 순서일 수 있습니다.
  • Stream distinct()는 상태 저장 중간 작업입니다.
  • 정렬된 병렬 스트림과 함께 distinct()를 사용하면 상당한 버퍼링 오버헤드로 인해 성능이 저하될 수 있습니다. 이 경우 순차 스트림 처리를 사용하세요.

distinct()를 사용하여 중복 요소 제거

스트림 distinct() 메서드를 사용하여 컬렉션에서 중복 요소를 제거하는 방법을 살펴보겠습니다.

jshell> List<Integer> list = List.of(1, 2, 3, 4, 3, 2, 1);
list ==> [1, 2, 3, 4, 3, 2, 1]

jshell> List<Integer> distinctInts = list.stream().distinct().collect(Collectors.toList());
distinctInts ==> [1, 2, 3, 4]

Stream distinct() 및 forEach()를 사용하여 고유한 요소만 처리

distinct()는 중간 작업이므로 forEach() 메서드를 사용하여 고유한 요소만 처리할 수 있습니다.

jshell> List<Integer> list = List.of(1, 2, 3, 4, 3, 2, 1);
list ==> [1, 2, 3, 4, 3, 2, 1]

jshell> list.stream().distinct().forEach(x -> System.out.println("Processing " + x));
Processing 1
Processing 2
Processing 3
Processing 4

사용자 정의 개체로 스트림 distinct()

목록에서 중복 요소를 제거하기 위해 distinct()를 사용하는 간단한 예를 살펴보겠습니다.

package com.journaldev.java;

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

public class JavaStreamDistinct {

	public static void main(String[] args) {
		List<Data> dataList = new ArrayList<>();
		dataList.add(new Data(10));
		dataList.add(new Data(20));
		dataList.add(new Data(10));
		dataList.add(new Data(20));

		System.out.println("Data List = "+dataList);

		List<Data> uniqueDataList = dataList.stream().distinct().collect(Collectors.toList());

		System.out.println("Unique Data List = "+uniqueDataList);
	}

}

class Data {
	private int id;

	Data(int i) {
		this.setId(i);
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return String.format("Data[%d]", this.id);
	}
}

산출:

Data List = [Data[10], Data[20], Data[10], Data[20]]
Unique Data List = [Data[10], Data[20], Data[10], Data[20]]

distinct() 메서드는 중복 요소를 제거하지 않았습니다. Data 클래스에 equals() 메서드를 구현하지 않았기 때문입니다. 그래서 상위 클래스 Object equals() 메서드를 사용하여 동일한 요소를 식별했습니다. Object 클래스 equals() 메서드 구현은 다음과 같습니다.

public boolean equals(Object obj) {
    return (this == obj);
}

데이터 객체는 동일한 ID를 가지고 있지만 서로 다른 객체를 참조하고 있기 때문에 동일하지 않은 것으로 간주되었습니다. 그렇기 때문에 사용자 정의 개체와 함께 스트림 distinct() 메서드를 사용하려는 경우 equals() 메서드를 구현하는 것이 매우 중요합니다. equals() 및 hashCode() 메서드는 Collection 클래스 API에서 두 개체가 같은지 여부를 확인하는 데 사용됩니다. 따라서 둘 다에 대한 구현을 제공하는 것이 좋습니다.

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + id;
	return result;
}

@Override
public boolean equals(Object obj) {
	System.out.println("Data equals method");
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Data other = (Data) obj;
	if (id != other.id)
		return false;
	return true;
}

팁: "Eclipse > Source > Generate equals() and hashCode()” 메뉴 옵션을 사용하여 equals() 및 hashCode() 메서드를 쉽게 생성할 수 있습니다. equals() 및 hashCode() 구현을 추가한 후의 출력은 다음과 같습니다.

Data List = [Data[10], Data[20], Data[10], Data[20]]
Data equals method
Data equals method
Unique Data List = [Data[10], Data[20

참조: Stream distinct() API 문서