HOME > java > java8

Java8의 Stream distinct 사용 방법

JSFollow13 Jul 2018

Distinct

distinct의 사전적 의미는 '구별할 수 있는'입니다. 어떤 스트림에서 중복되는 아이템들을 모두 제거해주고 새로운 스트림을 반환합니다. 아래 코드에서 stream1.distinct()는 스트림에서 중복을 제거한 새로운 스트림을 반환하였습니다. 동일한 객체인지 판단하는 기준은 Object.equals(Object)의 결과 값입니다. String 객체의 경우 equals()가 이미 구현되어 있기 때문에 의도한대로 동작하였습니다.

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

결과

google
apple
samsung

Distinct - custom class 정의

위의 String은 equals()가 구현되어있어 distinct가 동작하였습니다. 새로 정의하는 class의 경우 distinct를 사용하려면 equals()가 재정의되어야 합니다. 중요한 것은 hashCode()도 재정의해야 한다는 것입니다. distinct는 내부적으로 hashCode()를 이용하여 객체가 서로 다른 것을 확인하고 equals()로 컨텐츠가 같은지 체크하는 것 같습니다. 둘 중에 하나라도 재정의되어 있지 않으면 의도한대로 동작하지 않습니다.

예제로 MyString 클래스를 정의하였습니다. 실행하여 결과를 확인하면 중복된 객체들이 모두 제거된 스트림이 생성되었습니다.

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

결과

google
apple
samsung