Java8에서 도입된 Stream의 distinct()에 대해서 알아보겠습니다.
1. Stream의 distinct() 메소드
distinct의 사전적 의미는 '구별할 수 있는'입니다. Stream에서 distinct() 메소드는 스트림에서 중복되는 요소들을 모두 제거해주고 새로운 스트림을 반환합니다.
아래 예제에서 stream1은 리스트에 대한 스트림이고, stream2는 stream1에서 중복이 제거된 요소들의 스트림이 됩니다. distinct()가 중복을 제거하고 새로운 스트림을 리턴합니다.
List<String> strings =
Arrays.asList("google", "apple", "google", "apple", "samsung");
Stream<String> stream1 = strings.stream();
Stream<String> stream2 = stream1.distinct();
stream2.forEach(System.out::println);Output:
google
apple
samsung참고로, distinct() 메소드에서 중복 요소를 확인할 때, 동일한 객체인지 판단하는 기준은 Object.equals(Object) 메소드입니다.
위의 예제에서 String 클래스는 equals()가 이미 구현되어 있어서 문제가 없는데 Custom 클래스를 사용한다면 올바르게 구현이 올바른지 확인해 볼 필요는 있습니다.
2. Custom 클래스에 대한 distinct() 사용 예제
distinct()에서 중복을 판별하는 기준이 equals()라고 하였습니다. 만약 커스텀 클래스에서 equals()를 재정의하지 않으면 기본적으로 상속받은 equals()를 사용합니다.
만약 클래스의 특정 요소만 같으면 동일 객체라고 판단하고 싶을 때는, equals()를 자신의 상황에 맞게 재정의해야 합니다.
주의할 점은, equals()를 재정의할 때 hashCode()도 함께 재정의해야 합니다. distinct()에서 중복 요소를 판별할 때 먼저 hashCode()를 이용하여 객체가 서로 다른지 확인하고 equals()로 같은지 체크하는 것 같습니다. 만약 둘 중에 하나라도 재정의되어 있지 않으면 올바르게 동작하지 않을 수 있습니다.
아래 예제는 MyString라는 커스텀 클래스를 정의하고 hashCode()와 equals()를 재정의하였습니다.
public class StreamExample5 {
public static void main(String args[]) {
List<MyString> myStrings =
Arrays.asList(new MyString("google"),new MyString("apple"),
new MyString("google"), new MyString("apple"), new MyString("samsung"));
Stream<MyString> stream3 = myStrings.stream();
Stream<MyString> stream4 = stream3.distinct();
stream4.forEach(System.out::println);
}
public static class MyString {
public String str;
public MyString(String str) {
this.str = str;
}
@Override
public boolean equals(Object o) {
if (o instanceof MyString) {
return str.equals(((MyString) o).str);
}
return false;
}
@Override
public int hashCode() {
return str.hashCode();
}
@Override
public String toString() {
return str;
}
}
}Output:
google
apple
samsungRelated Posts
- Java - Unsupported class file major version 61 에러
- Java - String.matches()로 문자열 패턴 확인 및 다양한 예제 소개
- Java - 문자열 공백제거 (trim, replace)
- Java - replace()와 replaceAll()의 차이점
- Java - ArrayList 초기화, 4가지 방법
- Java - 배열 정렬(Sorting) (오름차순, 내림차순)
- Java - 문자열(String)을 비교하는 방법 (==, equals, compare)
- Java - StringBuilder 사용 방법, 예제
- Java - 로그 출력, 파일 저장 방법 (Logger 라이브러리)
- Java IllegalArgumentException 의미, 발생 이유
- Java - NullPointerException 원인, 해결 방법
- Seleninum의 ConnectionFailedException: Unable to establish websocket connection 해결
- Java - compareTo(), 객체 크기 비교
- Java - BufferedReader로 파일 읽기
- Java - BufferedWriter로 파일 쓰기
- Java - BigInteger 범위, 비교, 연산, 형변환
- Java charAt() 함수 알아보기
- Java contains()로 문자(대소문자 X) 포함 확인
- Java - Set(HashSet)를 배열로 변환
- Java - 문자열 첫번째 문자, 마지막 문자 확인
- Java - 문자열 한글자씩 자르기
- Java - 문자열 단어 개수 가져오기
- Java - 1초마다 반복 실행
- Java - 배열을 Set(HashSet)로 변환
- Java - 여러 Set(HashSet) 합치기
- Java - 명령행 인자 입력 받기
- Java - 리스트 역순으로 순회, 3가지 방법
- Java - 특정 조건으로 리스트 필터링, 3가지 방법
- Java - HashMap 모든 요소들의 합계, 평균 계산
- Java - 특정 조건으로 HashMap 필터링
- Java - 싱글톤(Singleton) 패턴 구현
- Java - 숫자 왼쪽에 0으로 채우기
- Java - String 배열 초기화 방법
- Java - 정렬된 순서로 Map(HashMap) 순회
- Java - HashMap에서 key, value 가져오기