📙 목차
🧡 학습 목표
- 스트림이 무엇인지 학습한다.
1. 스트림(stream) 이란?
- 데이터를 효율적으로 처리할 수 있는 흐름
- 선언형 스타일로 가독성이 굉장히 뛰어나다.
- 데이터 준비 → 중간 연산 → 최종 연산 순으로 처리된다.
- 스트림은 컬렉션(List, Set 등)과 함께 자주 활용된다.
2. for 문 vs 스트림
for 문
public class Main {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
// for 명령형 스타일: 각 요소 * 10 처리
List<Integer> ret1 = new ArrayList<>();
for (Integer num : arrayList) {
int multipliedNum = num * 10; // 각 요소 * 10
ret1.add(multipliedNum);
}
System.out.println("ret1 = " + ret1);
}
}
스트림
public class Main {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
// 스트림 선언적 스타일: 각 요소 * 10 처리
List<Integer> ret2 = arrayList.stream().map(num -> num * 10).collect(Collectors.toList());
System.out.println("ret2 = " + ret2);
}
}
* ArrayList 를 List 로 받는 이유
- 다형성을 활용해 List 인터페이스로 ArrayList 구현체를 받으면 나중에 다른 구현체(LinkedList , Vector) 로 변경할 때 코드 수정을 최소화할 수 있기 때문이다.
- 실무에서 리스트를 선언할 때 대부분 아래와 같이 List 타입으로 받는 것을 권장한다.
List<Integer> arrayList = new ArrayList<>();
3. 스트림 살펴보기 (선언형 스타일)
스트림 처리 단계
- 데이터 준비 → 중간 연산 등록 → 최종 연산
단계 | 설명 | 주요 API |
1. 데이터 준비 | 컬렉션을 스트림으로 변환 | stream(), parallelStream() |
2. 중간 연산 등록 (즉시 실행되지 않음) |
데이터 변환 및 필터링 | map(), filter(), sorted() |
3. 최종 연산 | 최종 처리 및 데이터 변환 | collect(), forEach(), count() |
- 스트림은 데이터 처리를 위해 여러 API를 제공한다. <참고 자료>
Stream (Java Platform SE 8 )
A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream and IntStream: int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight())
docs.oracle.com
예제: 스트림을 사용하여 각 요소를 10배로 변환 후 리스트로 변환하기
- stream() → map() → collect() 순으로 데이터 흐름을 처리한다.
- stream(): 데이터 준비 - 데이터를 스트림으로 변환하여 연산 흐름을 만들 준비를 한다.
- map(): 중간 연산 등록 - 각 요소를 주어진 함수에 적용해서 변환한다.
- collect(): 최종 연산 - 결과를 원하는 형태(List, Set)로 수집한다.
arrayList
.stream() // 1. 데이터 준비
.map() // 2. 중간 연산 등록
.collect() // 3. 최종 연산
// 1. 데이터 준비: 스트림 생성
Stream<Integer> stream = arrayList.stream();
// 2. 중간 연산 등록: 각 요소를 10배로 변환 로직 등록
Stream<Integer> mappedStream = stream.map(num -> num * 10);
// 3. 최종 연산: 최종 결과 리스트로 변환
List<Integer> ret2 = mappedStream.collect(Collectors.toList());
// 한 줄로 표현 가능
List<Integer> ret2 = arrayList.stream() // 1. 데이터 준비
.map(num -> num * 10) // 2. 중간 연산 등록
.collect(Collectors.toList()); // 3. 최종 연산
4. 스트림과 람다식 활용
public class Main {
public static void main(String[] args) {
// ArrayList 선언
List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
// 직접 map() 활용해보기
// 1. 익명클래스를 변수에 담아 전달
Function<Integer, Integer> function = new Function<>() {
@Override
public Integer apply(Integer integer) {
return integer * 10;
}
};
List<Integer> ret3 = arrayList.stream()
.map(function)
.collect(Collectors.toList());
System.out.println("ret3 = " + ret3);
// 2. 람다식을 변수에 담아 전달
Function<Integer, Integer> functionLambda = (num -> num * 10);
List<Integer> ret4 = arrayList.stream()
.map(functionLambda)
.collect(Collectors.toList());
System.out.println("ret4 = " + ret4);
// 람다식 직접 활용
List<Integer> ret5 = arrayList.stream()
.map(num -> num * 10)
.collect(Collectors.toList());
System.out.println("ret5 = " + ret5);
}
}
5. 스트림 중간연산과 함께 사용하기
예시: 리스트에서 짝수만 10배로 변환하기
- 다양한 중간 연산을 조립하여 데이터 처리 흐름을 만들 수 있다.
- 중간 연산(filter() 와 map()) 을 조합하여 짝수만 10배 변환시킨다.
- 언적 코딩으로 코드의 유지 보수성과 가독성이 뛰어나다.
List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
// filter() + map() 사용 예제
List<Integer> ret6 = arrayList.stream() // 1. 데이터 준비: 스트림 생성
.filter(num -> num % 2 == 0) // 2. 중간 연산: 짝수만 필터링
.map(num -> num * 10) // 3. 중간 연산: 10배로 변환
.collect(Collectors.toList()); // 4. 최종 연산: 리스트로 변환
System.out.println(ret6); // 출력: [20, 40]
6. 실습 과제
filter를 람다식으로 활용해 보세요.
- 익명 클래스 활용
- 람다식 만들기
- 직접 람다식 대입
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Predicate<Integer> pred1 = new Predicate<Integer>() {
@Override
public boolean test(Integer i) {
return i % 2 == 0;
}
};
List<Object> ret1 = arrayList.stream().filter(pred1).collect(Collectors.toList());
System.out.println("ret1 = " + ret1);
Predicate<Integer> pred2 = (i -> i%2==0);
List<Object> ret2 = arrayList.stream().filter(pred2).collect(Collectors.toList());
System.out.println("ret2 = " + ret2);
List<Object> ret3 = arrayList.stream().filter(i -> i%2==0).collect(Collectors.toList());
System.out.println("ret3 = " + ret3);
}
}
'Java > 강의' 카테고리의 다른 글
[📃 자바 입문] 프로그래머스 - 무료 강의 (0) | 2025.04.30 |
---|---|
[📙 Java 문법 종합반] 3-7. 쓰레드(Thread) (0) | 2025.04.17 |
[📙 Java 문법 종합반] 3-5. 람다(Lambda) (0) | 2025.04.16 |
[📙 Java 문법 종합반] 3-4. 제네릭(Generic) (0) | 2025.04.16 |
[📙 Java 문법 종합반] 3-3. 컬렉션(Collection) (1) | 2025.04.16 |