일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Class
- Matrix
- 구현
- Math
- 코테
- hash table
- Number Theory
- implement
- string
- database
- dynamic programming
- 파이썬
- java
- 코딩테스트
- greedy
- 자바
- two pointers
- geometry
- Data Structure
- Stack
- bit manipulation
- sorting
- simulation
- Binary Search
- array
- SQL
- Method
- Tree
- Counting
- Binary Tree
- Today
- Total
코린이의 소소한 공부노트
스트림의 정의와 특징 본문
[스트림의 정의]
1. 스트림은 다양한 데이터 소스(컬렉션, 배열)를 표준화된 방법으로 다루기 위한 것이다.
- 컬렉션 프레임워크의 경우, List와 Set을 다루는 방법과 Map을 다루는 방법이 달라 완전히 표준화되었다고 말하긴 어렵다.
- 하지만 데이터 소스를 스트림으로 만들고 나면, 다루는 방법은 똑같다.
2. 스트림은 데이터의 연속적인 흐름을 말한다.
- 중간 연산을 0~n번 거친 후 최종 연산 0~1번을 거쳐 결과가 나온다.
// Stream<T> Collection.stream()을 이용해 스트림으로 변환(생성)
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream(); // 컬렉션을 스트림으로
Stream<String> strStream = Stream.of(new String[] {"a","b","c" }); // 배열을 스트림으로
Stream<Integer> evenStream = Stream.iterate(0, n->n+2); // 0,2,4,..가 들어있는 스트림
Stream<Double> randomStream = Stream.generate(Math::random); // 람다식을 이용한 생성
IntStream intStream = new Random().ints(5); // 난수 스트림(크기가 5)
[스트림이 제공하는 기능]
1. 중간 연산: 연산결과가 스트림인 연산. 반복적으로 적용가능
2. 최종 연산: 연산결과가 스트림이 아닌 연산. 스트림의 요소를 소모하므로 한 번만 적용가능
stream.distinct().limit(5).sorted().forEach(System.out::println)
// 중복제거 / 5개 자르기 / 정렬 // 출력
// 중간 연산 // 최종 연산
String[] strArr = { "dd","aaa","CC","cc","b" };
Stream<String> stream = Stream.of(strArr); // 문자열 배열이 소스인 스트림
Stream<String> filteredStream = stream.filter(s->s.length()%2==0); // 걸러내기(중간 연산)
Stream<String> distinctedStream = filteredStream.distinct(); // 중복제거(중간 연산)
Stream<String> sortedStream = distinctedStream.sorted(); // 정렬(중간 연산)
Stream<String> limitedStream = sortedStream.limit(5); // 스트림 자르기(중간 연산)
long total = limitedStream.count(); // 요소 개수 세기(최종연산) <- 실행해보기
System.out.println(total); // 3. 문자열의 길이가 짝수인 것은 3개뿐이다.
[스트림의 특징]
1. 스트림은 데이터 소스(원본)로부터 데이터를 읽기만 할 뿐 변경하지 않는다.(read-only)
List<Integer> list = Arrays.asList(3,1,5,4,2);
List<Integer> sortedList = list.stream().sorted() // list를 정렬해서
.collect(Collectors.toList()); // 새로운 List에 저장
System.out.println(list); // [3, 1, 5, 4, 2]
System.out.println(sortedList); // [1, 2, 3, 4, 5]
2. 스트림은 Iterator처럼 일회용이다. 필요하면 다시 생성해야 한다.
strStream.forEach(System.out::println); // 모든 요소를 화면에 출력(최종연산)
int numOfStr = strStream.count(); // 에러. 스트림이 이미 닫혔음
// java.lang.IllegalStateException: stream has already been operated upon or closed
3. 최종 연산 전까지 중간 연산이 수행되지 않는다.(지연된 연산)
IntStream intStream = new Random().ints(1,46); // 1~45범위의 무한 스트림
intStream.distinct().limit(6).sorted() // 중간 연산
.forEach(i->System.out.print(i+",")); // 최종 연산
// 무한 스트림이라 이런 코드가 불가능할 것 같지만, 가능한 코드다.
// 최종 연산 전까지 중간 연산들을 체크해놨다가 최종 연산 단계에서 체크해둔 중간 연산들을
// 실행하기 때문에 이런 코드가 가능한 것이다.
4. 스트림은 작업을 내부 반복으로 처리한다.
for(String str : strList) // 배열의 요소를 하나씩 꺼내서 출력하는 for문
System.out.println(str);
// 위의 for문을 스트림을 이용한 코드로 바꾸면
Stream.of(strList).forEach(System.out::println);
// 스트림의 forEach() 코드
void forEach(consumer<? super T> action){
Objects.requireNonNull(action); // 매개변수의 널 체크
for(T t : src) // 내부 반복
action.accept(T);
}
5. 스트림의 작업을 병렬로 처리한다.(병렬스트림 - 멀티쓰레드)
Stream<String> strStream = Stream.of("dd","aaa","CC","cc","b");
int sum = strStream.parallel() // 병렬 스트림으로 전환(속성만 변경)
.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
// parallel()의 반대는 sequential()
6. 기본형 스트림: IntStream, LongStream, DoubleStream
- 데이터 소스가 기본형일 때 사용한다.
- int는 스트림으로 변환하면 Integer로 오토박싱된다. 그래서 스트림을 사용할 때 int로 언박싱을 해야 한다.
- Stream<Integer>대신 IntStream사용함으로써 오토박싱/언박싱의 비효율이 제거된다.
- 숫자와 관련된 유용한 메서드를 Stream<T>보다 더 많이 제공한다. T가 어떤 타입인지 모르기 때문에 Stream<T>에서는 숫자와 관련된 메서드가 별로 없다.
'Java' 카테고리의 다른 글
스트림의 중간 연산 (0) | 2023.02.07 |
---|---|
스트림 생성하기 (0) | 2023.02.01 |
람다식과 메서드 참조 (0) | 2023.01.13 |
function 패키지와 메서드 (0) | 2023.01.12 |
함수형 인터페이스의 정의와 활용 (0) | 2022.12.29 |