(10분 기술 토크) 크리스, 로마에서 스트리밍 vs.

필터, 매핑과 같은 중간 작업과 수집과 같은 최종 작업을 통해 스트림을 생성하고 원하는 형태의 데이터를 얻을 수 있습니다.

for 문: 코드 블록으로 표현
스트림 파이프라인: 함수 객체로 표현
(함수 개체: 람다 식 또는 메서드 참조일 수 있습니다.)
이 표현 방법에는 몇 가지 제한 사항이 있습니다.

public int subtractByFor(int baseNumber, List<Integer> numbers) {
	for (int number : numbers) {
		if (number % 2 == 0) {
			baseNumber -= number;
		}
	}
	return baseNumber;
}

public int subtractByStream(int baseNumber, List<Integer> numbers) {
	numbers.stream()
			.filter(number ->number %2 == 0)
			.forEach(number -> baseNumber -= number); // 컴파일 에러
	return baseNumber;
}

진술을 위해

1. 외부 변수인 BaseNumber는 코드 블록 내에서 수정 가능

2. return 문을 사용하여 메서드를 종료하고 break 또는 continue를 통해 루프를 제어할 수 있습니다.

개울

1. 람다식으로 표현하기 때문에 람다식에 final을 붙이거나 실제로 final인 변수만 읽을 수 있으므로 외부변수 baseNumber는 수정할 수 없다.

2. 람다로 표현되는 스트림이 불가능하다

외부 반복(어떻게) vs 내부 반복(무엇)

중복 체크에서 중복이 제거된 요소의 개수를 구하는 코드

public int byFor(List<Integer> numbers) {
	Set<Integer> duplicationRemoved = new HashSet<>();
	for (int number : numbers) {
		duplicationRemoved.add(number);
	}
	return duplicationRemoved.size();
}

public int byStream(List<Integer> numbers) {
	return (int) numbers.stream()
			.distinct()
			.count();
}

1. for 문을 사용한 코드

중복을 허용하지 않는 Set에 데이터를 삽입하고 size 메소드를 통해 중복이 제거된 요소의 개수를 구한다.

특정 구현 로직이 외부에 노출되는 외부 반복 형식입니다.

논리가 노출되기 때문에 방법 지향 코드

2.Stream을 사용한 코드
특정 구현 로직이 외부에 노출되지 않는 내부 반복의 형태를 가집니다.

논리가 추상화되므로 무엇을 지향하는 코드

가독성 측면

public List<Crew> collectByFor(List<Crew> crewList) {
	List<Crew> result = new ArrayList<>();
	for (Crew crew : crewList) {
		if (crew.matchAgeRange(20, 40)) {
			if (crew.matchCourse(Course.BACKEND)) {
				if (crew.matchGender(Gender.FEMALE)) {
					result.add(crew);
				}
			}
		}
	}
}

public List<Crew> collectByStream(List<Crew> crewList) {
	return crewList.stream()
			.filter(crew ->crew.matchAgeRange(20, 40))
			.filter(crew -> crew.matchCourse(Course.BACKEND))
			.filter(crew -> crew.matchGender(Gender.FEMALE))
			.collect(Collectors.toList());
}

20~40대 백엔드 크루 중 여성 크루만 선발하는 코드

중첩된 if 문으로 인해 들여쓰기 깊이가 깊어 가독성이 떨어질 수 있습니다.

Stream의 경우 필터 체이닝을 통해 조건을 표현할 수 있기 때문에 보다 간결한 표현이 가능하다.


그러나 Stream은 가독성 측면에서 절대적으로 좋지 않습니다.
위의 코드는 Effective Java에서 발췌한 아나그램에 대한 것입니다.

Stream을 사용하는 코드를 보면 여러 수집이 있고 논리가 람다 식과 복잡하게 얽혀 있어 읽기 어려워 보입니다.
이 경우 왼쪽과 같이 for 문으로 표현된 코드가 읽기가 더 쉬울 수 있습니다.

public void printByFor(int() numbers) {
	for (int i : numbers) {
		for (int j = 0; j < i; j++) {
			System.out.println(i * j);
		}
	}
}

public void printByStream(int() numbers) {
	Arrays.stream(numbers)
			.forEach(i -> IntStream.range(0, i)
					.forEach(j -> System.out.println(i * j)));
}

위와 같이 단순한 double for 문의 경우에도 Stream은 for 문보다 복잡해 보일 수 있습니다.

디버깅 측면

스트림은 내부적으로 수행되는 작업이 많기 때문에 매우 복잡하게 출력됩니다.

또한 Stream은 Lazy 연산으로 작업을 수행하기 때문에 Stack Trace는 실제 라인과 다른 순서로 출력된다.

for 문은 간결하게 출력되므로 디버깅에 유리할 수 있습니다.

병렬의 차이


숫자의 합을 계산하는 예

여기서 숫자의 크기가 커지거나 프로그램이 메서드를 많이 호출하면 성능을 높여야 한다.
이 경우 병렬 처리를 고려할 수 있습니다.

오른쪽 코드에는 병렬 처리를 위해 Runnable을 구현하고 숫자의 합을 계산하는 SumThread 클래스를 작성했습니다.

왼쪽의 코드는 SumThread를 사용하여 숫자의 합을 병렬로 계산합니다.


표시된 블록은 전체 숫자 목록을 여러 하위 목록으로 나눕니다.


각 스레드가 하위 목록의 합을 계산하는 작업을 병렬로 처리하게 하고,


처리된 값은 끝에 추가되어 반환됩니다.

이렇게 Stream을 사용하지 않으면 병렬 처리를 위한 코드를 하나씩 작성해야 합니다.
(더 복잡한 로직을 병렬로 처리하는 것은 구현하기 더 어렵고 더 많은 주의가 필요하며, 데이터를 청크로 나누는 방법이나 가능한 동시성 문제를 고려해야 합니다.)

성능 차이

1. 배열 추가, 최대값

스트림: 스트림을 생성하는데, 생성 과정에서 여러 작업이 수행되며 스트림에 필요한 다른 객체를 생성하는 데 오버헤드가 발생합니다.

for : 추가 객체를 생성하지 않고 인덱스를 통해 메모리에 직접 액세스 -> 스트림에 비해 오버헤드가 없습니다.

2. 목록 추가, 최대값

잘 들리지 않습니다.

오늘날의 하드웨어는 충분히 빠르기 때문에 소프트웨어는 성능보다 다른 것에 더 신경을 쓰는 경향이 있습니다.
성능이 정말 중요한 프로그램이라면 고려할 수도 있겠지만 그렇지 않다면 성능보다는 유지보수와 가독성을 고려하는 것이 나을 수도 있습니다.

결론

Stream은 추상화된 API를 제공하고 무엇을 지향하는 코드를 작성할 수 있어 가독성에 이점이 있습니다.
그러나 Stream을 과도하게 사용하면 실제로 가독성이 떨어질 수 있습니다.

디버깅 측면에서 for 문은 스택 추적이 스트림보다 단순하고 명확하기 때문에 디버깅에 유리합니다.

Stream을 통한 병렬 처리는 개발자가 주의해야 할 부분을 Stream 내부에서 처리하기 때문에 간단합니다.

기본 유형을 처리할 때 for 문이 더 잘 수행됩니다.
그러나 컬렉션에서 성능 차이는 무시할 수 있습니다.

또한 오늘날에는 가독성 및 유지 관리 가능성과 같은 다른 고려 사항이 성능보다 더 중요합니다.

Stream 적용조건 (참고용)

일련의 요소를 일관되게 변환합니다.

요소의 순서 필터

요소의 순서 단일 작업을 사용하여 결합하십시오.

요소의 순서 컬렉션으로 모으다

요소의 순서 특정 조건을 만족하는 요소를 찾습니다.


참조

(10분 기술 토크) 크리스, 로마에서 스트리밍 vs.
https://www.youtube.com/watch?v=by8hb75i9X4&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=86&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC