이번 글은 Collector의 분할에 대해서 정리해보겠습니다.

분할 함수는 맵의 key로 Boolean을 반환합니다.

참 아니면 거짓 값을 갖는 두 그룹으로 분류돼 맵이 결과로 반환되게 됩니다.

예제를 통해 확인해보겠습니다.

먼저 예제에 쓰일 games 객체 리스트를 생성합니다.

List<Game> games = Arrays.asList(
		 new Game("CALL 1", 20000, "Shooting")
		,new Game("DIA 3", 30000, "RPG")
		, new Game("DIA 2", 40000, "RPG")
		, new Game("DIA 1", 50000, "RPG")
);

 

partitioningBy

games 객체 리스트에서 RPG 라는 타입으로 분할하여 분류하는 예제입니다. 

Boolean 타입의 각각 false, true의 key 값이 생성되고 partitioningBy에 인수로 넣은 프레디케이트 값에 따라 분류됩니다. 

Map<Boolean, List<Game>> partitionedGame = games.stream()
.collect(partitioningBy(game -> game.getType().equals("RPG")));

partitionedGame.forEach((k,v) -> {
	System.out.println("<"+k+">");
	v.forEach(game -> System.out.println(game.getName()));
	System.out.println();
});

결과값

RPG 타입과 Shooting 타입으로 분류됩니다.

<false>
CALL 1

<true>
DIA 3
DIA 2
DIA 1

 

다음 예제는 앞에서 정리한 groupingBy과 partitioningBy 같이 활용한 예제입니다.

Map<Boolean, Map<String, List<Game>>> rpgGameByType = games.stream()
	.collect(partitioningBy(game -> game.getType().equals("RPG")
	, groupingBy(Game::getType)));
		
rpgGameByType.forEach((k,v) -> {
	System.out.println(k + " >");
	v.forEach((key, value) -> {
		System.out.println(key + " >");
		value.forEach(game -> System.out.println(game.getName()));
	});
	System.out.println();
});

결과값

false >
Shooting >
CALL 1

true >
RPG >
DIA 3
DIA 2
DIA 1

 

다음은 partitioningBy을 사용하여 소수를 분류하는 예제를 확인해보겠습니다.

먼저 소수를 판단하는 리턴하는 정적 메서드를 작성하겠습니다.

앞에서 배운 rangeClosed 메서드로 범위를 정하고 noneMatch 메서드를 사용하여 어떤 값들을 

찾을 것인지 조건을 정합니다.

public static boolean isPrime(int num) {
	int root = (int) Math.sqrt((double) num);
	return IntStream.rangeClosed(2, root).noneMatch(i -> num % i == 0);
}

앞에서 만든 isPrime 메서드를 활용하여 소수와 소수가 아닌 수로 분류하는 스트림을 작성합니다.

public static Map<Boolean, List<Integer>> partitionPrimes(int num) {
	return IntStream.rangeClosed(2, num).boxed()
				.collect(partitioningBy(x -> isPrime(x)));
}

partitionPrimes 메서드를 사용하여 분류하는 테스트를 해봅니다.

1~10까지 소수를 분류하여 출력합니다.

System.out.println(partitionPrimes(10));

결과값

{false=[4, 6, 8, 9, 10], true=[2, 3, 5, 7]}

 

마치며

스트림과 컬렉터를 쭉 살펴보면서 정리하다 보니 기존 DB 레벨에서 사용하던 SQL 처리 기능들을 

많이 Java 코드로 처리할 수 있게 많이 고민을 한 것 같습니다.

이전 글에 groupingBy, maxBy, counting는 SQL에 groupBy, max, count와 매칭이 됩니다.

현업에 있으면서 여러 회사를 거치면서 DB 프로시저로만 모든 비즈니스 로직 구현한 곳도 봤고

프로시저 없이 SQL과 Java를 적절히 섞어서 비즈니스 로직이 구현된 곳을 가장 많이 본듯합니다.

점점 JPA가 자리 잡으면서 예전처럼 Mybatis 프레임워크 위에서 SQL를 직접 구현하는 경우는 점점 줄고 있는데요.

물론 case by case로 적절히 기술을 적용하고 사용해야겠지만 이제는 DB 프로시저나 SQL을 직접 비즈니스 로직

구현하는 경우는 거의 없어지지 않을까 싶습니다.

물론 아직도 개발자가 거의 없거나 개발팀이 없는 경우 최소한에 인력으로 운영하면서 리팩터링에 대한 시간을

아까워하는 곳이 많이 있기 때문에 어느 정도 수요는 유지될 것으로 생각됩니다.

'Java > Stream' 카테고리의 다른 글

Collector 그룹화  (0) 2022.11.01
Collector 요약  (0) 2022.10.28
스트림 생성  (0) 2022.10.27
기본형 특화 스트림  (0) 2022.10.27
리듀싱  (0) 2022.10.26

+ Recent posts