Search
☄️

스트림

태그
java

스트림이란

데이터의 연속적인 흐름으로, 다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것
다양한 데이터 소스: 컬렉션, 배열
기존에 다양한 데이터 소스를 표준화하는 방법으로 컬렉션 프레임워크가 있었음
하지만 List, Set과 Map의 특성과 사용 방법이 달라 완벽한 표준화라고는 할 수 없음
JDK1.8에서는 다양한 컬렉션과 배열을 같은 연산을 사용하여 결과를 낼 수 가 있게 됨
스트림에 대한 과정은 아래와 같음
컬렉션, 배열 -> 1. stream 만들기 -> 1. 중간 연산 -> ... -> 중간 연산 -> 3. 최종 연산 -> 결과 도출
Java
복사

1. 스트림 만들기

1.
list.stream(); // 컬렉션
2.
Stream.of(new String[]{”a”,”b”}); // 배열
3.
Stream.iterate(0, n→n+2)
4.
Stream.generate(Math::random);
5.
new Random().inits(5)

2. 중간 연산

연산 결과가 스트림인 연산. 반복적으로 적용 가능
stream.distinct().limit(5).sorted().forEach(System.out::println);
Java
복사
distinct(): 중복 제거
limit(n): n개 자르기
skip(n): 앞에서부터 n개 건너띄기
sorted(), sorted(Comparator comparator (정렬 기준)): 정렬
Comparator의 comparing()으로 정룔 기준을 제공
.sorted(Comparator.comparing(Student::getBan)) //반벌로 정렬 .forEach(System.out::println); (s)->s.getBan()Student::getBan으로 표현
Java
복사
filter(Predicate predicate(조건식)): 조건에 맞지 않는 요소 걸러내기
map(Function mapper): 변환 (Stream<T> → Stream<R>)
peek(): forEach()와 같지만 peek()은 중간 연산(스트림 요소를 소비 x), 중간 연산 중에 확인할 때 사용(디버깅 용도)
flatmap(): 스트림의 스트림을 스트림으로 변환(합침) ( Stream<String[]> → Stream<String> )
strArrStrm.flatMap(Arrays::stream);
Java
복사
→ string의 단어들을 stream으로 변환하고 싶을 때도 사용
String[] lineArr = { "Believe or not It is true", "Do or do not There is no try" }; String<String> lineStream = Arrays.stream(lineArr); lineStream.flatMap(line -> Stream.of(line.split(" +"))) //하나이상의 공백 .map(String::toLowerCase) .distinct() .sorted() .forEach(System.out::println); /* believe do is it no ... */
Java
복사

3. 최종 연산

연산결과가 스트림이 아닌 연산. 단 한번만 적용 가능(스트림의 요소를 소모)
스트림이 닫힘
forEach(Consumer action): 스트림의 모든 요소에 지정된 작업을 수행, 병렬스트림인 경우 순서가 보장되지 않음
forEachOrdered(Consumer action): 스트림의 모든 요소에 지정된 작업을 수행, 병렬스트림인 경우에도 순서가 보장됨
allMatch(Predicate predicate): 모든 요소가 조건을 만족시키면 true
anyMatch(Predicate predicate): 한 요소가 조건을 만족시키면 true
noneMatch(Predicate predicate): 모둔 요소가 조건을 만족시키지 않으면 false
findFirst(): 조건에 일치하는 첫번째 요소를 반환, 순차 스트림에 사용
findAny(): 조건에 일치하는 아무거나 하나를 반환, 병렬 스트림에 사용
reduce(T identity, BiFunction<U,T,U> accumulator, BinaryOperator<U> combiner): 스트림의 요소를 하나씩 줄여가며 누적 연산(accumulator) 수행
identity: 초기값(생략 가능)
accumulator: 이전 연산결과와 스트립의 요소에 수행할 연산
combiner: 병렬처리된 결과를 합치는데 사용할 연산(병렬 스트림)(생략 가능)
int a = 0 // identity for(int b : stream) a = a+b // sum() -> 이 식을 아래와 같이 표현 가능 intSream.reduce(0, (a,b)-> a+b )
Java
복사

스트림의 특징

스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않음
스트림은 Iterator처럼 일회용(필요하면 다시 스트림을 생성해야함)
최종 연산 전까지 중간 연산이 수행되지 않음 - 지연된 연산
지연된 연산으로 무한 스트림도 연산이 가능함
스트림은 작업을 내부 반복으로 처리함
stream.forEach(System.out::println);
Java
복사
→ 코드는 간결해지지만 성능 효율성은 떨어짐
스트림의 작업을 병렬로 처리 - 병렬스트림
FP는 빅데이터같은 대작업을 위해 필요
병렬 스트림이란 멀티스레드로 스트림 처리
strStream.parallel() // 병렬 스트림으로 전환(속성만 변경) .mapToInt(s -> s.length()).sum(); // 모든 문자열 길이의 합 (병렬 스트림으로 하여야 빨리 처리)
Java
복사
기본형 스트림 - IntStream, LongStream, DoubleStream
오토박싱 & 언박싱의 비효율이 제거됨(Stream<Integer> 대신 IntStream 사용)
Stream<Integer> 을 사용하면 1 → new Integer(1) 오토박싱 과정을 거침
마찬가지로 Integer → 1로 언박싱하는 과정을 거침
FP는 빅데이터 처리에 효율적이여야 함
그렇기 때문에 오토박싱, 언박싱 하는데 걸리는 시간을 없애야 함
이를 위해 기본형 스트림을 사용
IntStream 같은 경우 숫자와 관련된 유용한 메서드를 Strem<T>보다 더 많이 제공