ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 스트림의 최종연산
    Java 2022. 2. 10. 00:01

    이전 시간에 스트림의 중간 연산에 대해 알아보았습니다.

    https://junuuu.tistory.com/88?category=968252 

    스트림은 아래와 같은 주기를 가집니다.

    1. 스트림 생성

    2. 중간 연산 (0~ n번)

    3. 최종 연산 (0~1번)

     

    오늘은 스트림의 최종 연산에 대해 알아보겠습니다.

    최종 연산에는 스트림의 요소를 소요하며 스트림이 닫히기 때문에 한 번만 연산할 수 있습니다.

    중간 연산은 Stream을 반환하는 반면에 최종 연산은 int, boolean, Optional 등을 반환합니다.

     

    최종 연산에는 어떤것들이 있는지 보겠습니다.

    forEach(), forEachOrdered()

    void forEach(Consumer<? super T> action)		//병렬스트림인 경우 순서가 보장되지 않음
    void forEachOrdered(Consumer<? suepr T> action)	//병렬스트림인 경우에도 순서가 보장됨
    
    IntStream.range(1, 10).sequential().forEach(System.out::print);		//123456789
    IntStream.range(1, 10).sequential().forEachOrdered(System.out::print);	//123456789
    
    IntStream.range(1, 10).parallel().forEach(System.out::print);		//683295714
    IntStream.range(1, 10).parallel().forEachOrdered(System.out::print);	//123456789

    스트림의 모든 요소에 지정된 작업을 수행합니다.

    sequential()은 스트림의 작업을 직렬로 처리하도록 합니다.

    스트림은 기본적이으로 직렬로 처리하기 때문에 이를 생략해서 사용해도 됩니다.

    parallel()은 스트림의 작업을 병렬로 처리하도록 합니다.

    따라서 forEach를 사용할 경우에는 순서가 보장되지 않지만 forEachOrdered를 사용하면 순서가 보장됩니다.

     

    allMatch(), anyMatch(), noneMatch()

    boolean allMatch (Predicate<? super T> predicate) //모든 요소가 조건을 만족시키면 true
    boolean anyMatch (Predicate<? super T> predicate) //한 요소라도 조건을 만족시키면 true
    boolean noneMatch (Predicate<? super T> predicate) //모든 요소가 조건을 만족시키지 않으면 true
    
    boolean hasFailedStu = stuStream.anyMatch(s -> s.getTotalScore () <= 100); //성적이 100점보다 낮은 학생이 있는지?
    
    Optional<T> findFirst()	//첫번째 요소를 반환.	순차 스트림에 사용
    Optional<T> findAny()	//아무거나 하나를 반환.	병렬 스트림에 사용
    //Optional은 결과가 null일 수 있습니다.
    
    Optional<Student> result = stuStream.filter(s-> s.getTotalScore() <= 100).findFirst();
    Optional<Student> result = parallelStream.filter(s->s.getTotalScore()<=100).findAny();

    스트림의 조건을 검사하는 작업을 수행합니다.

    filter()를 사용하여 성적이 100점보다 낮은 학생들을 걸러내고 그중 첫 번째 학생을 결과로 반환합니다.

    filter()를 사용하여 성적이 100점보다 낮은 학생들을 걸러네고 병렬적인 쓰레드들 중에 찾은 아무 학생을 반환합니다.

    이때 학생의 순서는 알 수 없습니다.

     

    reduce()

    Optional<T> 		reduce(BinaryOperator<T> accumulator)
    T			reduce(T identity, BinaryOperator<T> accumulator)
    U			reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator<T> combiner)
    
    identity : 초기값
    accumulator : 이전 연산결과와 스트림의 요소에 수행할 연산
    combiner : 병렬처리된 결과를 합치는데 사용할 연산
    
    
    int count = intStream.reduce(0, (a, b) -> a + 1 );	//count()
    int sum = intStream.reduce(0, (a, b) -> a + b );	//sum()
    int max = intStream.reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b); // max()
    int min = intStream.reduce(Integer.MAX_VALUE, (a, b) -> a < b ? a : b); // min()

    스트림의 요소를 하나씩 줄여가며 누적연산을 수행

    첫 번째에 Optional <T>를 사용하는 이유는 identity(초기값)이 없기 때문에 초기값이 없다면 null값이 할당될 수 있음

    reduce(0 , (a,b) -> a+1)에서 0은 초기값을 의미하고 a+1은 0부터 1씩 증가하여 연산 결과를 누적하여 수행합니다.

     

    collect(), Collector

    Object collect(Collector collector)	//Collector를 구현한 클래스의 객체를 매개변수로 사용
    Object collect(Supplier supplier, BiConsumer accumulator, Biconsumer combiner) //잘 안쓰임
    
    //Collector : collect에 필요한 메서드를 정의해 놓은 인터페이스
    public interface Collector<T, A, R>
    Supplier<A>	supplier()
    Biconsumer<A, T> accumulator()
    BinaryOperator<A> combiner();
    Function<A, R> finisher();
    Set<Characteristics>	characteristics();

    reduce()는 전체에 대해서 한다면 collect()는 그룹별로 reduce()를 진행할 수 있습니다.

     

    Stream<String> fruits = Stream.of("banana", "apple", "mango", "kiwi", "peach", "cherry", "lemon");
    HashSet<String> fruitHashSet = fruits.collect(HashSet::new, HashSet::add, HashSet::addAll);
    for (String s : fruitHashSet) {
        System.out.println(s);
    }

    위의 코드는 스트림의 결과를 HashSet으로 변환하는 코드입니다.

    collect에 인자를 3개나 넣어야 하므로 사용하기 불편하기 때문에 Collectors 클래스를 사용하면 편리해집니다.

     

    Stream<String> fruits = Stream.of("banana", "apple", "mango", "kiwi", "peach", "cherry", "lemon");
    Set<String> fruitSet = fruits.collect(Collectors.toSet());
    for (String s : fruitSet) {
        System.out.println(s);
    }

    위의 코드는 Collectors 클래스를 사용한 코드입니다.

     

    출처

    자바의정석

    https://www.youtube.com/watch?v=M_4a4tUCSPU 

    https://codechacha.com/ko/java8-stream-collect/

     

    Java8의 Stream Collect 사용 방법 및 예제

    Collect는 Stream의 데이터를 변형 등의 처리를 하고 원하는 자료형으로 변환해 줍니다. List 또는 Set 자료형으로 변환하거나, joining 또는 Sorting하여 1개의 객체를 리턴하기도 합니다. 또는 아이템들

    codechacha.com

     

    'Java' 카테고리의 다른 글

    [Java] DTO, DAO, VO란?  (0) 2022.02.19
    [Java] Optional이란?  (0) 2022.02.11
    [Java] 스트림의 중간연산  (0) 2022.02.09
    [Java] Math.max() vs 삼항연산자  (0) 2022.02.07
    [Java] Comparator와 Comparable란?  (0) 2022.02.03

    댓글

Designed by Tistory.