aammddkkzxc
2024. 2. 21. 23:42
- BaseStream : 스트림 최 상위 인터페이스, 공통 메서드들이 정의 되어 있을 뿐, 코드에서 직접적으로 사용되지는 않는다.
- Stream : 객체 요소 처리 스트림
- IntStream, LongStream, DoubleStream : 기본형 스트림
- Stream<Integer> 대신 IntStream을 쓰는 것이 좋다 (오토박싱, 언박싱)
- Stream 보다 유용한 메서드를 더 제공 (sum, average 등)
주로 컬렉션과 배열에서 스트림 인터페이스 구현 객체를 얻지만 다양한 소스가 존재
- 컬렉션, 배열, 특정 범위의 수(int, long), 랜덤 수, 람다식(iterate() ⇒ 초기값 있음, generate() 초기값 없음), 디렉토리, 파일
- concat메소드로 스트림을 연결 할 수 있다.
스트림의 특징
- 스트림은 데이터 소스로부터 데이터를 읽기만 할 뿐 변경하지 않는다.
- 스트림은 Iterator처럼 일회용이다. (필요하면 다시 스트림을 생성해야함)
- 최종 처리가 시작되기 전까지 중간 처리는 지연된다
- 1 ~ 45 사이의 난수를 발생시키는 스트림
- 무한 스트림 이라서 스트림 요소 개수가 정해지지 않음 (요소를 달라는 대로 계속 생성한다)
- 중간 연산의 메서드 들이 차례로 실행된다면 intStream.distinct() 이 먼저 실행 된다는 뜻인데, 무한히 생성되고 있는 요소들을 중복을 제거한다는 것이 말이 안됨 (중복 제거를 위해서는 모든 요소를 기억하고 있어야 하며, 무한히 발생하면 이를 처리할 수 없다)
- 그럼에도 밑에 처럼 가능한 이유는 메소드가 호출 되었을 때 스트림이 바로 처리되는 것이 아니라 어떤 메소드를 수행할 지 체크만 해놨다가 최종 연산을 만나면 나중에 수행하기 때문
- 내부 반복으로 처리한다 (실제로 for문이 함수 안에 있음)
- 스트림의 작업을 병렬로 처리 - 병렬스트림 사용(멀티 쓰레드로 병렬처리), (parallel() 메소드)
중간처리와 최종 처리
중간처리 : 필터링, 매핑, 정렬, 그룹핑 등 (연산 결과가 스트림)
최종처리 : 합계, 평균, 카운팅, 최댓값, 최솟값 등 (연산 결과가 스트림이 아님, 스트림의 요소를 소모)
필터링
- dictinct() : 중복 제거, equals()메소드를 호출하여 동일 객체를 판단한다
- filter() : 매개값으로 주어진 Predicate가 true를 리턴하는 요소만 남김
매핑 : 스트림의 요소를 다른 요소로 대체하는 작업
- map() : 스트림의 요소를 하나씩 특정 값으로 변환합니다. 이렇게 변환된 값은 새로운 스트림으로 만들어짐. 주로 매개값 Function.
- flatMap() : A라는 요소는 A1, A2 요소로 대체되고, B라는 요소는 B1, B2로 대체된 후, A1, A2, B1, B2 요소를 가지는 새로운 스트림이 생성된다. 매개값 Function
- boxed() : int, long, double 요소를 박싱해서 Stream을 생성 ⇒ 리턴타입 Stream<Intege>, ~
정렬
- sorted() : 객체를 Comparable구현 방법에 따라 정렬(기본 오름차순), 객체 요소일 경우 Comparable을 구현하지 않으면 sorted()메소드를 호출했을 때 ClassCastException이 발생한다.
- sorted(Comparator<T>) : 객체를 주어진 Comparator에 따라 정렬
루핑 : 요소 전체를 반복한다는 뜻
- peek() : 중간 처리 메서드이며, 후에 최종 처리 메서드를 호출하지 않는다면 아무일도 일어나지 않음, 매개값 Consumer
- forEach() : 최종 처리 메서드, 매개값 Consumer
커스텀 집계
- reduce() : 요소를 하나씩 줄여가며 누적 연산 수행
수집
- collect() : 요소들을 필터링 또는 매핑한 후 요소들을 수집하는 최종 메소드, 매개변수 Collectors
- Collector : 수집에 필요한 메소드를 정의해 놓은 인터페이스
- Collectors
- Collector인터페이스의 구현 클래스는 아니다
- Collectors 클래스의 메서드로 리턴타입이 Collector 인터페이스 타입 구현체들을 제공한다는 뜻
- Collector 인터페이스의 인스턴스를 생성하는 유틸리티 클래스, 다양한 기능 제공
- toList(), toSet(), toCollection(), toMap() : 스트림을 컬렉션으로 변환
- toArray() : 스트림을 배열로 변환
- groupingBy() : 컬렉션의 요소들을 그룹핑해서 Map 객체를 생성
static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier)
- 자바에서의 위와 같이 비슷한 유틸리티 클래스들
- Arrays, Collections, Objects 가 있다
Optional
- null을 직접 다루는 것은 위험 ⇒ 간접적으로 null다루기 위해 존재하는 Optional<T> 클래스
- if문으로 다루면 코드가 지저분해짐
- null을 포함한 모든 데이터를 저장할 수 있는 Wrapper 클래스
- 집계 값 저장, 디폴트 값 설정 가능, 집계 값 처리하는 Consumer도 등록 가능
- null대신 빈 Optional객체를 사용하자
메소드 | |
static <T> Optional<T> empty() | 아무런 값도 가지지 않는 비어있는 Optional 객체를 반환 |
static <T> Optional<T> of(T value) | null이 아닌 명시된 값을 가지는 Optional 객체를 반환 null 이 들어오면 NPE 가 발생 |
static <T> Optional<T> ofNullable(T value) | 명시된 값이 null이 아니면 명시된 값을 가지는 Optional 객체를 반환하며, 명시된 값이 null이면 비어있는 Optional 객체를 반환 |
메소드 | 설명 |
T get() | Optional 객체에 저장된 값을 반환함. |
T orElse(T other) | 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 값을 반환함. |
T orElseGet(Supplier<? extends T> other) | 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 람다 표현식의 결과값을 반환. |
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) | 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 예외를 발생시킴. |
boolean isPresent() | 저장된 값이 존재하면 true를 반환하고, 값이 존재하지 않으면 false를 반환함. |
Optional 의 장점
- 명시적으로 변수에 대한 null 가능성을 표현할 수 있다.
- null 체크를 직접 하지 않아도 된다.
- Null Point Exception 이 발생할 가능성이 있는 값을 직접 다룰 필요가 없다.
Optional 의 단점
- Wrapper 클래스이기 때문에 두 개의 참조를 가지므로 생성 비용이 비싸다.
- 직렬화 불가능하기 때문에 클래스의 인스턴스 필드로 사용하면 안된다.
- 필드로 사용하기 위해 고안된 것이 아니기 때문에 값을 반환하는 용도로 사용해야 한다.
출처
(도서)이것이 자바다
자바의 정석 유튜브 강의