[Java] stream vs for
글 작성자: SeoArc
이전에 한번 확인했던 내용이지만,
자바를 통해 프리코스를 수행하던 도중 다시 또 궁금증이 생기고 기억이 흐릿하여 작성해본다.
아마 자바를 공부해본 사람이라면 다 고민해봤을 내용이다.
※ 해당 내용은 우아한Tech 유튜브 채널의 "[10분 테코톡] 크리스, 로마의 stream vs for" 내용을 참고하였다
해당 영상의 자세한 내용은 https://www.youtube.com/watch?v=by8hb75i9X4 이 링크를 통해 보면된다.
코드
먼저 다음 코드는 Java 1부터 지원한 기본적인 for문이다.
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
다음은 Java 5부터 지원한 foreach문이다.
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
for (Integer i : list) {
System.out.println(i);
}
}
기존 for문에 비해 가독성이 좋아지고, Index를 직접 작성하는 방식이 아니기 때문에 OutOfRangeException이 발생할 확률이 적어 안정성이 올라갔다.
다음은 Java 8부터 지원하는 stream 구문이다.
public void introduceStream(List<Integer> numbers) {
return numbers.stream()
.filter(number -> number > 5)
.map(Distance::new)
.collect(Collectors.toList());
}
for vs stream
표현 방식
- for: 코드 블록
- stream: 함수 객체
- lambda식으로 표현하기 때문에 지역 변수를 수정할 수 없다.
- continue, break 로직을 사용할 수 없다.
내부 반복 vs 외부 반복
- for문은 구현 로직이 외부에 노출되는 외부 반복 형태이다. -> 로직이 외부에 노출되어 있기 때문에 How 중심의 코드라고 볼 수 있다.
- stream은 구현 로직이 외부에 노출되지 않는 내부 반복 형태이다. -> 로직이 추상화되어 있어 What 중심의 코드라고 볼 수 있다.
디버깅
- stream
- 내부적으로 수행되는 작업이 많기 때문에 stack trace가 복잡하다.
- 지연 연산으로 작업을 수행하기 때문에 실제 라인과는 다른 순서로 stack trace가 출력된다.
- 많은 내부 수행 작업과 지연 연산으로 인해 디버깅이 어려울 수 있다.
- for
- stack trace가 간결하게 출력되어 디버깅에 유리할 수 있다.
병렬 처리
for문을 사용한다면 직접 병렬 처리를 위한 코드를 작성해 주어야 한다. 때문에 복잡한 로직들을 병렬처리할 때 신경 쓸 것(데이터, 동시성 문제 등)이 많아진다. 하지만 병렬 stream(parallelStream())을 이용하면 stream이 내부적으로 처리해 주기 때문에 보다 쉽게 병렬처리를 표현할 수 있다.
성능
- 원시타입 배열의 경우
- for는 나온지 오래된 만큼 stream에 비해 JVM에서 최적화가 많이 이루어졌다. 때문에 for문이 stream보다 성능상의 이점을 보인다.
- 또한 stream을 사용하려면 stream 객체를 생성해야 하는데 생성 과정에서 여러 작업들이 이루어지고 stream에서 필요한 다른 객체를 생성하는데 오버헤드가 발생한다. 반면 for의 경우에는 추가적인 객체 생성 없이 index를 통해서 메모리에 직접 접근을 하기 때문에 stream에 비해서 오버헤드가 발생하지 않는다.
- Collection의 경우
- 성능차이가 크지 않음을 확인할 수 있는데, 이는 박싱 및 언박싱에 대한 오버헤드 발생으로 인해 큰 성능차이가 띄지 않는다.
요즘은 하드웨어의 발전으로 인해 소프트웨어에서 성능보다 다른 점들을 더 신경쓰는 추세이다.
때문에, 성능이 중요한 프로그램이라면 성능을 신경 써야겠지만, 그렇지 않다면 성능보다는 유지보수, 가독성 등을 고려하는 것이 더욱 좋을 수 있다.
stream을 적용하기 좋은 조건
- 원소들의 시퀀스를 일관되게 변환한다.
- 원소들의 시퀀스를 필터링한다.
- 원소들의 시퀀스를 하나의 연산을 사용해 결합한다.
- 원소들의 시퀀스를 컬렉션에 모은다.
- 원소들의 시퀀스에서 특정 조건을 만족하는 원소를 찾는다.
'Language > Java' 카테고리의 다른 글
[Java] 아무 생각 없이 생성했는데 동일한 객체? (0) | 2023.03.09 |
---|---|
[Java] abstract class vs interface (0) | 2023.01.20 |
[Java] 3. Iterator (0) | 2022.08.17 |
[Java] 2. List (0) | 2022.08.12 |
[Java] 1. Collections Framework (0) | 2022.08.11 |
댓글
이 글 공유하기
다른 글
-
[Java] 아무 생각 없이 생성했는데 동일한 객체?
[Java] 아무 생각 없이 생성했는데 동일한 객체?
2023.03.09 -
[Java] abstract class vs interface
[Java] abstract class vs interface
2023.01.20 -
[Java] 3. Iterator
[Java] 3. Iterator
2022.08.17 -
[Java] 2. List
[Java] 2. List
2022.08.12