Stream의 Collectors

조경찬 (Jo Gyungchan)·2023년 11월 1일
0

자바

목록 보기
5/5
post-thumbnail

Collectors

새롭게 알게된 Stream의 Collectors 기능을 적어보겠습니다.

List<Integer> numbers = List.of(1, 2, 3, 1);

위의 numbers 변수를 통해 다양한 기능을 학습해보겠습니다.

toList


Collectors.toList()

@Test
void toList() {
	List<String> result = numbers.stream()
				.map(String::valueOf)
				.collect(Collectors.toList());

	assertThat(result).containsExactly("1", "2", "3", "1");
}

가장 기본적인 형태입니다.
각각의 숫자들을 String으로 변환하여 변환된 값들을 List<String>으로 반환해줍니다.


Collectors.toCollection()

만약 구체적인 클래스인 LinkedList로 반환받고 싶으면 어떻게 해야될까요??
이때는 toCollection() 메서드를 사용하면 됩니다.

코드를 통해 보겠습니다.

@Test
void toCollection() {
	LinkedList<String> result = numbers.stream()
                .map(String::valueOf)
                .collect(Collectors.toCollection(LinkedList::new));

	assertThat(result).containsExactly("1", "2", "3", "1");
}

toCollection(LinkedList::new)를 통해 LinkedList로 반환받을 수 있었습니다.


Collectors.toUnmodifiableList()

또한 불변 List로 반환받을 수 있습니다.

List<Integer> result = numbers.stream()
               .collect(Collectors.toUnmodifiableList());

당연히 불변이기 때문에 반환된 List의 내부 값을 변경하려고 하면 예외가 발생합니다.

@Test
void toUnmodifiableList() {
	List<Integer> result = numbers.stream()
                .collect(Collectors.toUnmodifiableList());

	assertThatThrownBy(() -> result.add(10))
                .isInstanceOf(UnsupportedOperationException.class);
}

toSet

Set으로 바꾸기 위한 방법 또한 List와 유사합니다.

  • Collectors.toSet()
  • Collectors.toCollection(LinkedHashSet::new)
  • Collectors.toUnmodifiableSet()

마지막의 List대신 Set을 붙여준다는 차이만 있기 때문에, 예시 코드만 첨부하겠습니다.

@Test
void toSet() {
	Set<Integer> result = numbers.stream()
                .collect(Collectors.toSet());

	assertThat(result).containsExactly(1, 2, 3);
}

@Test
void toCollection() {
	LinkedHashSet<Integer> result = numbers.stream()
                .collect(Collectors.toCollection(LinkedHashSet::new));

	assertThat(result).containsExactly(1, 2, 3);
}

@Test
void toUnmodifiableSet() {
	Set<Integer> result = numbers.stream()
                .collect(Collectors.toUnmodifiableSet());

	assertThatThrownBy(() -> result.add(4))
                .isInstanceOf(UnsupportedOperationException.class);
}

Collectors.collectingAndThen()

이번에 새로 알게 된 기능 중 굉장히 유용하게 사용할 수 있을 거 같은 것 중 하나입니다.

collecting을 먼저 진행한 결과를 통해 새로운 값을 만들 수 있음!!

이해하기 쉽게 예제 클래스를 제가 만들어보았습니다.

class Score {
	private final List<Integer> numbers;

	public Score(List<Integer> numbers) {
		this.numbers = numbers;
	}

	public List<Integer> getNumbers() {
		return numbers;
	}
}

다음과 같이 List<Integer>를 통해 생성할 수 있는 Score 객체가 있다고 과정해봅시다.

@Test
void collectingAndThen() {
	List<String> source = List.of("1", "2", "3", "4");

	Score score = source.stream()
                .map(Integer::parseInt)
                .collect(Collectors.collectingAndThen(Collectors.toList(), Score::new));
                //변환된 값들을 List로 만들고, 이 값을 통해 Score 객체를 생성한다.

	assertThat(score.getNumbers()).containsExactly(1, 2, 3, 4);
}

그럼 다음과 같이 변환된 값들을 List로 만들고, 이 값을 통해 Score 객체를 생성할 수 있습니다.

굉장히 유용하다 생각이 들었고, 여러 곳에서 적용하여 사용해보자 생각이 들었습니다.


📝 마치며

아직도 모르는 기능이 많고, 얼른 배우고 싶다는 생각이 가득해지는 것 같습니다.
꾸준히 성장하는 개발자가 되길~~

profile
한걸음씩 성장하는 개발자

0개의 댓글