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 클래스이기 때문에 두 개의 참조를 가지므로 생성 비용이 비싸다.
  • 직렬화 불가능하기 때문에 클래스의 인스턴스 필드로 사용하면 안된다.
  • 필드로 사용하기 위해 고안된 것이 아니기 때문에 값을 반환하는 용도로 사용해야 한다.

 

 

출처

 

(도서)이것이 자바다

자바의 정석 유튜브 강의