⚡ 개요
Stream의 경우 자바8에서 추가된 이후 람다를 활용한 기술이다. 확실히 Stream을 사용해서 로직을 처리하다 보면 가독성도 올라가고 제공되는 함수가 다양하다 보니 계속해서 stream을 활용해서 처리하려고 하는 부분이 존재한다.
Stream에서 froEach를 사용하면서 연산이 진행되는 동안에 로직에 대한 처리가 필요한 경우가 있다.
이때 과연 forEach를 사용하는것이 옮은 방향성인가에 대해서 한번 정리를 하려고 한다.
⚡ 내용
기본적으로 stream은 "데이터의 흐름" 이다.
그러다 보니 기존 for-loop와 다르게 강제로 종료를 시키는 방법이 존재하지 않는다. 결국 전체를 읽어서 처리하는 경우가 아닌 중간에 로직적으로 멈춰야 하는 경우가 생긴다면 비효율이 발생하게 된다.
실제 공식문서에 따르면 종단 연산자인 forEach 연산은 최종 연산 중 기능이 가장 적고 가장 덜 Stream 다우며 수행한 계산 결과를 보고 할 때만 이용해야 한다. 결과를 보여주기 이상을 하면 잘못된 코드일 가능성이 높다.
stream 내에는 중간 연산을 도와주는 filter, map, reduce, sort 등을 제공해주기 때문에 forEach 의 경우는 최종 연산에서만 사용하는 걸 추천한다고 생각을 한다.
하지만 그럼에도 forEach 내부에서 연산을 처리해야 한다면 향상된 for 문을 사용하는 것을 추천한다.
break를 통해서 연산 도중에 로직을 종료도 가능하고 stream 보다는 가독성이 떨어질 수도 있지만 큰 차이는 없다고 생각을 한다.
🚀 샘플 코드
샘플 코드를 작성하려고 했는데 크게 뭔가 설명할 게 없다....😅
위의 상황에 대해서 왜 사용했을 때 비효율적인지 간단하게만 보고 넘어가면 좋을 거 같다.
/* 랜덤으로 로또 번호를 출력 한다고 가정을 했을떄
* 만약 일단 100개의 랜덤 번호를 받아서 배열로 저장하고
* 제일 먼저 6개를 출력한다고 했을때를 한번 살펴보자.
* */
// for loop
for (int i = 0; i < 100; i++) {
if (i > 6) {
break;
}
System.out.print("[" + (random.nextInt(45) + 1) + "]");
}
// stream forEach
IntStream.range(0, 100).forEach(randomInt -> {
if (randomInt > 6) {
return;
}
System.out.print("[" + (random.nextInt(45) + 1) + "]");
});
// stram forEach (중간 연산자 포함)
IntStream.range(0, 100)
.filter(randomInt -> randomInt < 7)
.forEach(outRandumInt -> {
System.out.print("[" + (random.nextInt(45) + 1) + "]");
});
위의 코드에서 6자리의 로또 번호를 구하는 것이기 때문에 총 100개의 인수를 랜덤으로 받았더라도 6개가 채워지는 순간 멈춰야 한다. 샘플 소스이기 때문에 당연히 예제로는 적합하지 않을 수 있다.
for loop는 6번째 인수를 넘어가는 순간 break를 걸기 때문에 멈추게 되지만 stream의 경우는 100번까지 돌고 나서야 멈추게 된다. 중간 연산자를 포함하면 충분이 처리가 가능하지만 위의 예제와 같은 상황이 오지 않는다면 매우 비효율적인 코드가 될 거라고 생각을 한다.
'Java' 카테고리의 다른 글
[Pythod] 파이썬 개발 도전 (2) (0) | 2023.12.10 |
---|---|
[JAVA] java 21 LTS 릴리즈 내용 정리 (0) | 2023.09.20 |
[JAVA] String isEmpty 및 isBlank 사용 정리 (0) | 2023.07.29 |
[JPA] 하이버네이트(Hibernate) 에 대한 내용 정리 (0) | 2023.05.01 |
[Java] Wrapper Class 의 캐싱에 대한 내용 정리 (0) | 2023.04.16 |