티스토리 뷰

개념

  • 스트림은 고유 요소로 이루어진 스트림을 반환하는 중간 연산인 distinct 메서드를 지원한다.

    • 고유 여부는 객체의 equalshashCode 메서드를 통해 판단한다.

예제

  • 아래 예제에서 사용되는 내용들은 다양한 상황을 연출하기 위해서 임의로 만들어진 내용이므로 특정 속성에 대해서 왜 저 타입이 사용되었는지 의문을 가지지 말자!

  • 예제 코드에서 사용되고 있는 스펙

    1. Java 15 preview (record라는 새로운 클래스 개념을 사용하기 위해서 해당 프리뷰 버전을 사용. 하위 버전의 경우는 일반 클래스를 생성한 후 getter를 만들고 사용하면 됨) - 참고
    2. JUnit 5
    3. Gradle 6.7
  • 소스 코드

기본 데이터 생성

public record Song(int no, String title, String albumName, String artist) {
    @Override
    public boolean equals(Object song) {
        return getClass() == song.getClass() && artist.equals(((Song) song).artist);
    }

    @Override
    public int hashCode() {
        return artist.hashCode();
    }
}
private final DistinctUsage distinctUsage = new DistinctUsage();
private final List<Song> songs = List.of(
        new Song(1, "Bohemian Rhapsody", "A Night at the Opera", "Queen"),
        new Song(2, "2002", "Speak Your Mind", "Anne-Marie"),
        new Song(3, "Blueming", "Love Poem", "IU"),
        new Song(4, "Love Poem", "Love Poem", "IU"));

중복 숫자 제거

  • 숫자가 담긴 리스트가 주어졌을 때 중복된 숫자를 제거하는 메서드를 만들어보자.
public List<Integer> getDistinctNumbers(List<Integer> lists) {
    return lists.stream()
            .distinct()
            .collect(Collectors.toList());
}
  • 테스트
@Test
@DisplayName("중복 숫자 제거")
void getDistinctNumbersTest() {
    final var expect = List.of(1, 2, 8, 4);
    final var result = distinctUsage.getDistinctNumbers(List.of(1, 2, 2, 8, 4, 1, 4));
    assertIterableEquals(expect, result);
}
  • 테스트가 가볍게 성공한다.

중복된 가수 이름 제거

  • 이번에는 우리가 만든 커스텀 클래스(Song) 를 사용해서 리스트를 만들고 중복을 제거해보자.
public List<Song> getSongsWithDistinctArtist(List<Song> songs) {
    return songs.stream()
            .distinct()
            .collect(Collectors.toList());
}
  • 사실 위의 예제와 크게 다른 점은 없다.

  • distinct 메서드 자체가 파라미터를 가지고 있지 않기 때문에 오버로딩 정도의 예제다.

  • 여기서 주의할 점은 커스텀으로 만든 클래스의 경우 Number 타입이나 String 타입과 같은 Java의 기본 데이터 형태를 사용할 때와 다르게 equalshashCode 메서드를 오버라이딩해줘야 한다.

    • 그렇지 않을 경우 distinct가 정상적으로 작동하지 않는다.
  • 여기서는 가수 이름 을 통해 중복을 제거하도록 테스트해보자.

@Test
@DisplayName("중복된 가수 이름 제거")
void getSongsWithDistinctAlbumNameTest() {
    final var result = distinctUsage.getSongsWithDistinctArtist(songs);
    result.forEach(System.out::println);
    assertEquals(3, result.size());
    assertEquals("Bohemian Rhapsody", result.get(0).title());
    assertEquals("2002", result.get(1).title());
    assertEquals("Blueming", result.get(2).title());
}
  • 콘솔에 다음과 같은 실행 결과와 함께 테스트가 성공한다.

  • 여기서 Song 클래스의 equalshashCode 메서드를 다음과 같이 오버라이딩했기 때문에 테스트가 정상적으로 성공했다.

    • 둘 중 하나라도 오버라이딩하지 않았다면 distinct 메서드가 정상적으로 작동하지 않아서 테스트가 실패한다.

이상 Stream API에서 사용하는 중간 연산 중 distinct 메서드의 간단한 사용법에 대해 살펴보았다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함