리덕션, 병렬 스트림

gustjtmd·2022년 1월 16일
0

Java

목록 보기
36/40

리덕션과 reduce 메소드

리덕션은 '데이터를 축소하는 연산'을 뜻한다. 앞서 보인 sum도 리덕연 연산에 해당한다.
다수의 데이터를 더하여 ''합'이라는 하나의 데이터만 남겼으니 sum도 리덕션 연산이다.
그러나 조금 다른 리덕션을 진행하는 메소드가 있다.

T reduce(T identity, BinaryOperator<T> accumulator) //Stream<T>에 존재.

이 메소드는 다르리덕션 연산에 비해 활용도가 높다.
다른 리덕션 연산의 경우 연산의 내용이 이미 정해진 상태이지만 reduce는 전달하는 람다식에
의해 연산의 내용이 결정되기 때문이다 
이 메소드의 동작 원리를 설명하기 위해 두 번째 매개변수 형인 BinaryOperator<T>의 추상
메소드를 보이겠다.

BinaryOperator<T>	T apply(T t1, T t2)

reduce 호출시 위의 메소드 apply에 대한 람다식을 인자로 전달해야 한다. 
그러면 reduce는 내부적으로 apply를 호출하면서 스트림에 저장된 데이터를 다음과 같은 방식으로
줄여 나간다.

예제를 통해 확인해보자.

------------------------------------------------------------------------

public class ReduceStream {
    public static void main(String[] args) {
        List<String> ls = Arrays.asList("Box", "Simple", "Complex", "Robot");

        BinaryOperator<String> lc = (s1,s2)->{
            if(s1.length()>s2.length())
                return s1;
            else
                return s2;
        };
        String str = ls.stream()
                .reduce("",lc);
        System.out.println(str);
    }
}
--------------------------------------------------------------------------
Complex

다음은 위 예제에서 작성한 람다식이다. 이 람다식이 reduce 메소드가 호출하는 apply 메소드의
몸체가 된다.

BinaryOperator<String> lc = (s1,s2)->{
            if(s1.length()>s2.length())
                return s1;
            else
                return s2;
        };
        
인자로 두 개의 문자열을 전달받아서 그 길이를 비교하여 긴 문자열을 반환하는 람다식이다.
그리고 이 람다식을 다음과 같이 reduce 메소드를 호출하면서 인자로 전달하였다.

String str = ls.stream()
		.reduce("",lc);	//스트림이 빈 경우 빈 문자열 반환.
        
reduce는 '첫 번째 인자로 전달된 값'을 스트림이 빈 경우에 반환을 한다 뿐만 아니라
스트림이 비어 있지 않은 경우에는 이를 스트림으첫 번째 데이터로 간주하고 리덕션을 진행한다.
떄문에

String str = ls.stream()
		.reduce("Empty Stream",lc); 
으로 작성시 "Empry Stream"이 가장 긴 문자열이 되어 reduce 메소드의 반환 값이 될수있다.

병렬 스트림

하나의 작업을 둘 이상의 작업으로 나누어서 동시에 진행하는 것을 '병렬 처리'라 한다.
자바는 언어 차원에서 '병렬 처리'를 지원한다. 따라서 쉽게 병렬 처리를 진행할수 있게 되었다.

-----------------------------------------------------------------------
public class ReduceParallelStream {
    public static void main(String[] args) {
        List<String> ls = Arrays.asList("Box", "Simple", "Complex", "Robot");

        BinaryOperator<String> lc = (s1,s2) ->{
            if(s1.length() > s2.length())
                return s1;
            else
                return s2;
        };

        String str = ls.parallelStream()    //병렬 처리를 위한 스트림 생성
                    .reduce("",lc);
        System.out.println(str);
    }
}

Complex

이전 예제와의 유일한 차이점은 다음 문장에서 
stream이 아닌 parallelStream메소드를 호출했다는 것이다.

String str = ls.parallelStream()    //병렬 처리를 위한 스트림 생성
                    .reduce("",lc);
                    
이렇게 병렬 스트림을 생성하면 이어지는 연산들은 CPU의 코어 수를 고려하여 적절하게 병렬로
처리가 된다.

병렬 처리가 무조건 좋아보이지만 좋은건 아니다. 때로는 병렬처리가 일반 처리보다 느릴때도 있다.

우리는 그걸 적절히 판단하여 사용해야 한다.
profile
반갑습니다

0개의 댓글