티스토리 뷰

개발/JAVA

[JAVA] Collectors

애쿠 2023. 1. 26. 01:24

 

먼저 함수형 인터페이스와 stream을 소개했다.

 

stream의 최종 연산에서 Stream.collect()를 통해서 데이터를 변환해준다. collect의 파라미터로 Collectors 클래스를 주로 사용하는데, 내용이 꽤나 괜찮아보여서 정리해보려고한다.


1. Collectors 클래스

collectors 클래스는 데이터 변환 뿐만 아니라 다양한 기능을 제공한다.

 

  1. stream 요소들을 List, Set, Map 등의 자료형으로 변환
  2. stream 요소들의 결합(joining)
  3. stream 요소들의 통계(최대, 최소, 평균 등)
  4. straem 요소들의 그룹화(groupingBy)와 분할(partitioningBy)

데이터를 변환해서 return 해주는 것 뿐 만아니라, 조회 후 데이터를 정제해주는 쿼리와 같은 역할도 한다.


1.1 stream 요소들을 특정 자료형으로 변환

Collectors 클래스에서 미리 정의된 매서드를 이용해 변환할 수 있다.

List<String> list = Arrays.asList("ab", "cd", "eee", "ffff", "g", "hig");
// list -> list
list.stream().collect(Collectors.toList());
// list -> set
list.stream().collect(Collectors.toSet());
// list -> another Collections
list.stream().collect(Collectors.toCollection(LinkedList::new));
// list -> map
list.stream().collect(Collectors.toMap(Function.identity(), String::length));

toList와 toSet의 경우 이전 Collection의 타입을 그대로 가져온다. 특정 Collection을 사용하려면 toCollection을 써야한다.

Map은 key, value 쌍으로 구현되기 때문에, key를 생성해주는 별도의 코드가 필요하다.


1.2 stream 요소들의 결합

// joining
String joining = list.stream().collect(Collectors.joining());
System.out.println(joining);
// joining with delimiter
String joiningD = list.stream().collect(Collectors.joining("+"));
System.out.println(joiningD);
// joining with delimiter and prefix, suffix
String joiningps = list.stream().collect(Collectors.joining("+", "PREFIX ", " SUFFIX"));
System.out.println(joiningps);

result

abcdeeeffffghig
ab+cd+eee+ffff+g+hig
PREFIX ab+cd+eee+ffff+g+hig SUFFIX

스트림 요소를 하나의 객체로 결합할 수 있다. 결합하는 과정에서 구분자, 접두사, 접미사를 추가할 수 있다. String을 대상으로는 꽤 유용할 수 있지만 타 객체에는 적용하기 어려워 보인다.


1.3 stream 요소들의 통계

1.3.1 summarizingDouble/Long/Int()


xxxSummaryStatics 객체를 받아 위와 같은 함수를 return한다. 이와 같은 매서드들은 아래와 같이 있다.

 - averagingDouble/Long/Int(), summingDouble/Long/Int()

counting(), maxBy()/minBy()

평균, 합산, stream 요소의 갯수, 최대값, 최소값을 return 해준다. 별다르게 설명할 내용이 없다. 대부분 쿼리에서 처리해 줄 수 있는 정보다.


1.4 straem 요소들의 그룹화(groupingBy)와 분할(partitioningBy)

사실 이기능에 대해서 정리해보고 싶어서 윗 내용을 정리한거나 다름이 없다. groupingBy는 그룹화할 정보를 첫 파라미터로 받고 두번째 파라미터로는 변경하고 싶은 Collection을 선택할 수 있다. 예제가 스트링 리스트라 간단하게 작성해 봤다.

1.4.1 groupingBy

Map<Integer,List<String>> map = list.stream().collect(Collectors.groupingBy(String::length, Collectors.toList()));
        System.out.println(map.get(2));

result

[ab, cd]

Collectors.toList() 자리엔 Set 외에도 다른 Collection이나 내가 생성한 객체 등이 들어갈 수 있다. 변경된 타입에 따라서 당연히 Map 변수의 key-value도 변경되어야 할 것이다.

1.4.2 partitioningBy

Map<Boolean, List<String>> map = list.stream()
        .collect(Collectors.partitioningBy(s -> s.length() > 2));
System.out.println(map.get(true));

result

[eee, ffff, hig]

partitioningBy는 predicate를 파라미터로 받아, collection을 조건에 맞게 나눠준다. 이렇게 쓰는게 맞는지는 잘 모르겠지만, 공식 문서 Collectors에서는 predicate만 받는 것을 보니 맞는 것 같다... 그럼 map의 키는 true/false 밖에 없는 게 아닌가...?

 


2. 마치며

통계 관련 매서드들은 대부분 쿼리단에서 정리가 가능한 정보들이라 크게 유용하지는 않은 것 같다.

 

내가 하는 작업에서는 stream의 타입 변환은 대부분 객체를 받는 List라 groupingBy와 partitioningBy를 이용한다면 중복 쿼리를 자주 만들지 않고, 데이터를 정리할 수 있게끔, 나름대로 유용하게 쓸 수 있을 것 같다.

'개발 > JAVA' 카테고리의 다른 글

[JAVA] 이중콜론(::) 표현식  (0) 2023.01.26
[JAVA] Optional 클래스  (1) 2023.01.26
[JAVA] Stream  (1) 2023.01.26
[JAVA] 함수형 인터페이스  (1) 2023.01.26
[JAVA] TemporalAdjusters  (0) 2023.01.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
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
글 보관함