본문 바로가기
JAVA/[JAVA] Stream

[Java] Functional extends

by oncerun 2022. 2. 17.
반응형
  • 자바에서도 렉시컬 스코프가 존재한다.

  • 내부 함수가 존재하는 한 렉시컬 스코프가 존재하며 외부 함수 변수 또한 포함되어 있다. 이렇게 생성 당시의 환경을 가진 함수를 클로저라 한다. 이때 외부 함수의 변수들은 암묵적으로 final로 취급된다. 

  • 이 개념을 응용한 것이 Curry이다. 여러 개의 매개변수를 받는 함수를 중첩된 여러 개의 함수로 쪼개어 매개 변수를 한 번에 받지 않고 여러 단계에 걸쳐서 나누어 받을 수 있게 하는 기술입니다.
    Function<Integer, Function<Integer, Integer>> curryAdd = x -> y -> x + y;
    Function<Integer, Integer> addThree = curryAdd.apply(3);
    Integer result = addThree.apply(10);​
    addThree는 3이라는 값을 항상 기억하고 있다가. 다음 apply가 호출되었을 때 3을 더해주는 함수가 되었습니다.


  •  Lambda의 계산은 그 Lazy Evaluation이 적용되어 결과 값이 필요할 때 계산된다. 이를 통해 불필요한 계산을 줄이거나 해당 코드의 실행 순서를 의도적으로 미룰 수 있다.

    종결처리를 하는 순간에 계산이 필요함을 느끼고 계산을 처리합니다. 만약 종결처리를 호출하지 않는다면 불필요한 계산은 진행하지 않고 로직이 흘러갈 것입니다. 

    두 가지 예제가 있습니다.
    if (returnTrue() || returnFalse()) {
        log.info("first Test");
    }
    
    if (or(returnTrue(), returnFalse())) {
        log.info("second Test");
    }
    
    if(lazyOr(() -> returnTrue(), () -> returnFalse())){
        log.info("third Test");
    }
     public static boolean or(boolean a, boolean b) {
        log.info(" call or()");
        return a || b;
    }
    
    public static boolean lazyOr(Supplier<Boolean> x, Supplier<Boolean> y) {
        return x.get() || y.get();
    }
    
    public static boolean returnTrue() {
        log.info(" call returnTrue() ");
        return true;
    }
    
    public static boolean returnFalse() {
        log.info(" call returnFalse() ");
        return true;
    }

    기본적으로 메서드의 호출과정에서 인자의 값을 먼저 확인한 후 메서드를 호출하기 때문에
    두 번째 테스트(or()) 경우 || 연산이 효과가 없이 두 메서드가 호출됩니다.


    하지만 세 번째 테스트의 결과는 다릅니다.


    이번에는 실행 순서를 생각하고 다음 코드의 진행을 생각해 봅시다.
    Stream<Integer> integerStream = Stream.of(1, 2, -1, -3, -23, 10, 5124)
            .filter(x -> x > 0)
            .peek(System.out::println)  //잠깐 힐끗
            .filter(x -> x % 2 == 0);
    log.info("Before collect  integers");
    List<Integer> integers = integerStream.collect(Collectors.toList());
    log.info("After collect  integers {}", integers);​

    스트림의 데이터가 필터링 -> peek()을 통한 출력 -> 필터링 -> Before 로그 -> 리스트 생성 -> After로그
    결과는 다음과 같습니다.

    collect의 종결 처리 메서드가 실행되는 순간 중간처리를 하고 종결되어 리스트를 반환한 것을 알 수 있습니다.
    이처럼 종결처리를 호출하기 전까지 계산을 미루는 행위를 Lazy Evaluation이라고 합니다.

반응형

'JAVA > [JAVA] Stream' 카테고리의 다른 글

Optional  (0) 2022.10.12
Stream (3)  (0) 2022.02.16
Stream (2)  (0) 2022.02.15
Stream  (0) 2022.02.12
Method Reference  (0) 2022.02.09

댓글