이론 정리/java
Stream(스트림)
철매존
2023. 1. 12. 00:02
728x90
Stream(스트림)
다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것
여기서 데이터 소스란, 컬렉션이나 배열처럼 여러가지 데이터들을 저장하고 있는 것을 의미한다.
그동안은 표준화된 방법을 위해 Collection Framework(List, Set, Map)을 사용해 왔는데 이 Collection Framework의 List, Set, Map은 서로의 사용법이 달랐었다. -> 즉, 사실 제대로된 표준화가 아니었다.
JDK1.8부터는 stream을 통해 진짜 저 Collection Framework를 제대로 통일시킬 수 있었다.
Stream 장점
- 컬렉션(List, Set, Map)과 배열을
- Stream에 태운다.
- Stream의 사용 방식대로 쓰면
- 다른 데이터소스인데도 같은 메서드를 사용해서 같은 결과를 낼 수 있다!!
Stream 구조
- 중간 연산
- N번(여러번) 수행
- 최종 연산
- 딱 1번만 수행(안할수도 있고)
- 연산 결과가 스트림이 아니다.
- 스트림의 요소를 소모하는 연산임
중간 연산을 통해 여러번의 연산을 진행하고, 이를 원하는 데이터 양식으로 변환한 다음에 마지막으로 최종 연산을 통해 원하는 결과를 얻을 수 있는 것이다.
- distinct
- 중복제거(제거 하고나도 stream형식은 유지된다.)
- limit
- 5개만(자르고 나도 당연히 stream)
- sorted
- 분류(이것도 뭐 당연히 stream)
- forEach
- Stream을 하나씩 꺼냄
- 여기서는 println으로 하나씩 꺼내서 출력하는 것이다.
- Stream을 하나씩 꺼냄
Stream 생성
int형 arraylist를 Stream으로
List<Integer> list = Arrays.aslist(1,2,3,4,5);
Stream<Integer> intStream = list.stream();
String 배열을 Stream으로
Stream<String> strStream = Stream.of(new String[]{"a", "b", "c"});
0, 2, 4, 6 ...
Stream<Integer> evenStream = Stream.iterate(0, n->n+2);
람다식
Stream<Double> randomStream = Stream.generate(Math::random);
난수 스트림
IntStream intStrea = new Random().ints(5);
Stream 특징 (1)
- 스트림은 데이터 소스로부터 데이터를 읽기만 할 뿐 이를 변경하지는 않는다.
- 그러니까 Stream을 사용해서 읽어온 데이터에 따로 로직을 적용해도 기존 데이터는 그대로임
- Stream은 Iterator처럼 일회용이다.
- 쓴 다음에 또 쓸일이 있으면 Stream을 다시 생성해야 한다.
- 최종 연산 전까지 중간연산이 수행되지 않는다. - 지연된 연산
IntStream intStream = new Random().ints(1, 46); // 1~45범위의 무한 스트림 -> 계속해서 난수를 생성한다.
intStream.distinct(0).limit(6).sorted() // 중간연산
.forEach(i->System.out.println(i+",")); // 최종연산
지금 이 코드를 보면
- 난수가 계속해서 생성됨
- 그 난수들의 중복제거
- 6개 뽑기
- 정렬
- 출력
인데, 계속 생겨나는 난수의 중복제거? 이게 될리가 없다.
근데 Stream에서는 이거를 지연된 연산으로 처리하여 가능하게 해준다.
Stream 특징 (2)
- 스트림은 작업을 내부 반복으로 처리한다.
- 반복문을 그냥 forEach같은걸로 쓰는거임
Stream 특징 (3)
- 스트림 작업을 병렬로 처리 - 병렬스트림 지원
- 즉, 멀티쓰레드로 처리한다는 것이다.
- 이 내용을 참조하자
- 즉, 멀티쓰레드로 처리한다는 것이다.
Stream<String> strStream = Stream.of("dd", "aaa", "CC", "cc", "b");
int sum = strStream.parallel() // 병렬 스트림으로 전환(속성만 변경)
.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
- 기본형 스트림 - IntStream, LongStream, DoubleStream
- Stream<Integer> 이런거 안해도 된다.
- 이런 방식으로 하면 오토박싱&언박싱을 하게 된다.
- 기본타입 -> wrapper : 오토박싱
- wrapper -> 기본타입 : 언박싱
- 오토박싱/언박싱에서의 비효율을 제거해준다.
- 이런 방식으로 하면 오토박싱&언박싱을 하게 된다.
- 기본형 스트림에서만 가능하다.
- 기본형 스트림은 메서드도 좀 다양하게 지원한다.
- Stream<Integer> 이런거 안해도 된다.