티스토리 뷰
반응형
이번 글에서는 자바에서 사용하는 그룹핑 방법을 간단히 소개해드리고자 글을 작성하게 되었습니다. 회사에서 사용하는 기술 중 하나는 JPA인데, JPA에서는 기본적으로 Group By 옵션을 사용할 수 없습니다. 적어도 CustomRepository 를 만들어 Native Query 로 작성을 하거나, QueryDSL 을 사용해서 쿼리를 변경해야 합니다. 이 글은 MyBatis의 방법으로 GROUP BY 를 사용하는 대신 자바에서 사용할 수 있는 방법을 제시하고자 합니다.
Collertors 클래스 사용하기
1. groupingBy()
데이터를 그룹핑해서 Map으로 리턴합니다. Thread safe 하지 않습니다.
Lists.newArrayList()
.stream()
.collect(Collectors.groupingBy(o -> o));
2. groupingByConcurrent()
데이터를 그룹핑해서 Map으로 리턴하는 것은 groupingBy와 같은 방법이지만 Thread safe 합니다.
Lists.newArrayList()
.stream()
.collect(Collectors.groupingByConcurrent(o -> o));
Example
model
@Getter
@Setter
@Builder
private static class Temp {
private String group;
private String uuid;
}
Test
@Test
public void listSample() {
List<Temp> list = Arrays.asList(
Temp.builder().group("A").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("A").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("B").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("C").uuid(UUID.randomUUID().toString()).build()
);
list.stream()
.collect(Collectors.groupingBy(Temp::getGroup))
.forEach((key, value) -> {
log.info("key :{}, value : {}", key, value.size());
});
}
결과
key :A, value : 2
key :B, value : 1
key :C, value : 1
주의할 점
Group By 의 Key 값이 Nullable 인 경우 NullPointerException 을 주의하여야 합니다.
Caused by: java.lang.NullPointerException: element cannot be mapped to a null key
at java.util.Objects.requireNonNull(Objects.java:228)
at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:907)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
대안코드
@Test
public void listSample() {
List<Temp> list = Arrays.asList(
Temp.builder().group("A").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("A").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("B").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group("C").uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group(null).uuid(UUID.randomUUID().toString()).build(),
Temp.builder().group(null).uuid(UUID.randomUUID().toString()).build()
);
list.stream()
.collect(
Collectors.toMap(
Temp::getGroup,
x -> {
List<Temp> subList = new ArrayList<>();
subList.add(x);
return subList;
},
(left, right) -> {
left.addAll(right);
return left;
},
HashMap::new
)
)
.forEach((key, value) -> {
log.info("key :{}, value : {}", key, value.size());
});
}
결과
key :null, value : 2
key :A, value : 2
key :B, value : 1
key :C, value : 1
참고링크
반응형
'Server' 카테고리의 다른 글
[Java] Encode, Decode 함수 사용하기 (4) | 2022.02.04 |
---|---|
특정 잡만 수행하고 싶을 때 (1) | 2022.01.10 |
Job & Step 병렬 처리 하기 (2) | 2022.01.05 |
Spring Batch Job Repository (1) | 2021.12.30 |
AWS EC2 Ubuntu GUI 설정 (1) | 2021.12.24 |
DataGrip 에서 SSH 터널링으로 DB 접근하기 (2) | 2021.12.22 |
댓글
공지사항