11. 스트림(Stream)
1) 스트림이란?
- 다양한 데이터 소스를 통일된 방법으로 다루기 위한 것
- 스트림이 제공하는 기능: 중간연산, 최종 연산
- 과정: 스트림 생성 -> 중간연산 -> 최종연산
2) 스트림의 특징
- 스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않음(원본 유지)
- 스트림은 Iterator처럼 일회용(필요시 스트림 재 생성해서 사용)
- 최종 연산 전까지 중간연산 미수행(지연된 연산)
- 작업을 내부 반복으로 처리한다.
- 작업을 병렬처리한다. (병렬 스트림)
*기본형 스트림(IntStream, LongStream, DoubleStream)
- 오토박싱&언박싱의 비효율 제거됨(Stream<Integer> 대신 IntStream사용)
- 숫자와 관련된 유용한 메소드를 Stream<T>보다 많이 제공
3) 스트림의 생성
- 컬렉션으로부터 스트림 생성
List<Integer> 참조변수 = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = List.stream();
- 배열로부터 스트림 생성
Stream<String> strStream = Stream.of("a","b","c"); // 가변인자
Stream<String> strStream = Arrays.Stream(new String[]{"a","b","c"});
- 특정 범위의 정수를 요소로 갖는 스트림 생성
IntStream intStream = IntStream.range(1, 5); // range 끝 값 미포함, rangeClosed 끝 값 포함
- 난수를 요소로 갖는 스트림 생성
IntStream intStream = new Random().ints(); // 무한 스트림
intStream.limit(5).forEach(System.out::println); // 5개 요소 출력
IntStream intStream = new Random().ints(5); // 크기가 5인 난수 스트림을 반환
*유한생성자: ints(long streamSize, int begin, int end) // 유한 스트림
*무한생성자: ints(int begin, int end) // 무한 스트림
- 람다식을 소스로 하는 스트림 생성
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) // 이전 요소에 종속
static <T> Stream<T> generate(Supplier<T> s) // 이전 요소에 독립
- 파일을 소스로 하는 스트림 생성
Stream<Path> Files.list(Path dir) // 매개변수: 파일 혹은 디렉토리
4) 스트림의 중간연산 메소드
- 스트림 자르기
skip(long n) -> 앞에서부터 n개 건너뛰기
limit(maxSize) -> maxSize 이후 요소 잘라냄
- 스트림의 요소 걸러내기
filter(Predicate<? super T> predicate) -> 조건에 맞지 않는 요소 제거
distinct() -> 중복 제거
- 스트림 정렬하기 sorted()의 매개변수
기본정렬: (Comparator.naturalOrder()), ((s1, s2) -> s1.compareTo(s2)), (String::compareTo)
역순정렬: (Comparator.reverseOrder()), (Comparator.<String>naturalOrder().reversed())
대소문자미구분: (String.CASE_INSENSITIVE_ORDER) // reversed()로 역순 정렬 가능
길이순정렬: (Comparator.comparing(String::length)) // comparingInt -> no 오토박싱
- 스트림의 요소 변환
map(Function<? super T, ? extends R> mapper) -> Stream<T> -> Stream<R>
- 스트림 요소 소모 없이 조회
peek() -> forEach랑 같은 형식
5) 스트림 타입 변환 표
스트림 타입 변환 정리표 | ||
From | To | 변환 메소드 |
스트림 -> 기본형 스트림 | ||
Stream<T> | IntStream LongStream DoubleStream | MapToInt (Function<T> mapper) mapToLong (ToLongFunction<T> mapper) mapToDouble(ToDoubleFunction<T>mapper) |
기본형 스트림 -> 스트림 | ||
IntStream LongStream DoubleStream | Stream<Integer> Stream<Long> Stream<Double> | boxed() |
Stream<U> | mapToObj (DoubleFunction<U> mapper) | |
기본형 스트림 -> 기본형 스트림 | ||
Stream<T> IntStream | LongStream DoubleStream | asLongStream() asDoubleStream() |
스트림 -> 부분 스트림 | ||
Stream<T> IntStream | Stream<T> IntStream | skip (long n) limit (long maxSize) |
두 개의 스트림 -> 스트림 | ||
Stream<T>, Stream<T> | Stream<T> | concat (Stream<T> a, Stream<T> b) |
IntStream, IntStream | IntStream | concat (IntStream a, IntStream b) |
LongStream, LongStream | LongStream | concat (LongStream a, LongStream b) |
DoubleStream, DoubleStream | DoubleStream | concat (DoubleStream a, DoubleStream b) |
스트림의 스트림 -> 스트림 | ||
Stream<Stream<T>> | Stream<T> | flatMap (Function mapper) |
Stream<IntStream> | IntStream | flatMapToInt (Function mapper) |
Stream<LongStream> | LongStream | flatMapToLong (Function mapper) |
Stream<DoubleStream> | DoubleStream | flatMapToDouble (Function mapper) |
스트림 <-> 병렬 스트림 | ||
Stream<T> IntStream LongStream DoubleStream | Stream<T> IntStream LongStream DoubleStream | parallel() // 스트림->병렬 스트림 sequential() // 병렬 스트림 -> 스트림 |
스트림 -> 컬렉션 | ||
Stream<T> IntStream LongStream DoubleStream | Collection<T> | collect (Collectors.toCollection (Supplier factory)) |
List<T> | collect (Collectors.toList()) | |
Set<T> | collect (Collectors.toSet()) | |
컬렉션 -> 스트림 | ||
Collection<T>, List<T>, Set<T> | Stream<T> | stream() |
스트림 -> Map | ||
Stream<T> IntStream LongStream DoubleStream | Map<K,V> | collect(Collectors.toMap(Function key, Function value)) collect(Collectors.toMap(Function key, Function value, BinaryOperator merge)) collect(Collectors.toMap(Function key, Function value, BinaryOperator merge, Supplier mapSupplier)) |
스트림 -> 배열 | ||
Stream<T> | Object[] | toArray() |
T[] | toArray(IntFunction<A[]> generator) | |
IntStream LongStream DoubleStream | int[] long[] double[] | toArray() |
6) Optional<T>과 OptionalInt
- Optional<T>: 'T'타입 객체의 래퍼(Wrapper)클래스
- Optional객체의 값 가져오기
get(): Optional 객체에 저장된 값 반환 // null이면 예외발생
orElse(""): Optional 객체에 저장된 값이 null 일 때 "" 반환
orElseGet(String::new): 람다식 사용가능 () -> new String()
orElseThrow(NullPointerException::new): null일 때 예외 발생
- isPresent(): if(Optional객체의 값==null) return false; else return true;
- 기본형 값을 감싸는 래퍼클래스: OptionalInt, OptionalLong, OptionalDouble
getAs타입() 으로 값을 얻음 // ex) getAsInt()
7) 스트림의 최종연산
- 모든 요소에 지정작업 수행
forEach(Consumer<? super T> action): 병렬스트림인 경우 순서 미보장
forEachOrdered(Consumer<? super T> action): 병렬스트림인 경우에도 순서 보장
- 스트림을 배열로 변환
toArray(): 스트림의 모든 요소를 Object배열에 담아 반환
toArray(IntFunction<A[]> generator) : 스트림의 모든 요소를 A타입의 배열에 담아 반환
- 조건검사
allMatch(Predicate<? super T> predicate): 모든 요소가 조건을 만족시키면 true
anyMatch(Predicate<? super T> predicate): 한 요소라도 조건을 만족시키면 true
noneMatch(Predicate<? super T> predicate): 모든요소가 조건을 만족시키지 않으면 true
- 조건 일치 요소 탐색
findFirst(): 첫 번째 요소를 반환(순차 스트림에서 사용)
findAny(): 아무 요소나 하나를 반환(병렬 스트림에서 사용)
- 스트림에 대한 통계정보 제공: count(), sum(), average(), max(), min()
- 요소를 하나씩 줄여가며 누적연산 수행: reduce() // 초기값, 작업(주로 람다식) 필요
8) collect(), Collector, Collectors
- collect()는 Collector를 매개변수로 하는 스트림의 최종 연산
- 그룹별 reduce() 이용이 가능
- Collector는 수집에 필요한 메소드를 정의해놓은 인터페이스
- Collector 인터페이스
supplier() : 결과 누적할 곳 // 반환 타입: Suppier<A>
accumulator() : 누적 방법 // 반환 타입: BiCounsumer<A, T>
combiner() : 결합 방법(병렬) // 반환 타입: BinaryOperator<A>
finisher() : 최종 변환 // 반환 타입: Function<A, R>
characteristics() : 컬렉터의 특성이 담긴 Set을 반환 // 반환 타입: Set<Characteristics>
- Collectors클래스는 다양한 기능의 컬렉터를 제공
변환: mapping(), toList(), toSet(), toMap(), toCollection() 등
통계: counting(), summingInt(), averagingInt(), maxBy(), minBy(), summarizingInt() 등
문자열 결합: joining()
리듀싱: reducing()
그룹화와 분할: groupingBy(), partitioningBy(), collectingAndThen()
9) Collectors의 메소드
- 스트림을 컬렉션으로 변환: toList(), toSet(), toMap(), toCollection()
- 스트림의 통계정보 제공: counting(), summingInt(), maxBy(), minBy() 등
- 스트림 리듀싱: reducing()
- 문자열 스트림의 요소를 모두 연결: joining()
- 스트림의 요소를 이등분: partitioningBy()
- 스트림의 요소를 그룹화: groupingBy()
'프로그래밍 > Java' 카테고리의 다른 글
[Java 요약 정리] 13. AWT(Abstract Window Toolkit) (0) | 2018.12.28 |
---|---|
[Java 요약 정리] 12. 입출력(I/O) (0) | 2018.12.28 |
[Java 요약 정리] 10. 람다식(Lambda Expression) (0) | 2018.12.27 |
[Java 요약 정리] 9. 쓰레드(Thread) (0) | 2018.12.27 |
[Java 요약 정리] 8. 애너테이션(Annotation) (0) | 2018.12.26 |