Lazy Evaluation
- Lambda의 계산은 그 결과값이 필요할 때가 되어서야 계산된다.
- 이를 이용하여 불필요한 계산을 줄이거나 해당 코드의 실행 순서를 Lazy Evaluation 의도적으로 미룰 수 있다.
public class LazyEvaluation {
public static void main(String[] args) {
// 경우 1.
if (or(returnTrue(), returnFalse())) {
System.out.println("true");
}
// 경우 2.
if (lazyOr(() -> returnTrue(), () -> returnFalse())) {
System.out.println("true");
}
}
public static boolean or(boolean x, boolean y) {
return x || y;
}
// Lazy Evaluation
public static boolean lazyOr(Supplier<Boolean> x, Supplier<Boolean> y) {
return x.get() || y.get();
}
public static boolean returnTrue() {
System.out.println("Returning true");
return true;
}
public static boolean returnFalse() {
System.out.println("Returning false");
return false;
}
}
- 위의 코드에서 경우 1 과 경우 2의 차이는 뭘까?
- 경우 1은 반환값이 true, Returning true, Returning false 가 나온다. -> 그 이유는 returnTrue(), returnFalse() 메소드를 모두 호출하기 때문이다. -> 최적화 되지 못했다.
- 반면 경우 2의 경우에는 returnTrue() 만 호출 되었다. -> returnTrue() 이미 true 를 반환하기 때문에 굳이 returnFalse() 메소드를 호출할 필요가 없는 것이다.
- 이게 가능한 이유는 매개변수의 타입이 Supplier 이기 때문에 get() 메소드를 호출하기 전까지는 실행되지 않기 때문이다.
Stream 에서의 Lazy Evaluation
- Stream 에서도 Lazy Evaluation 이 적용되어 있다.
Stream<Integer> integerStream = Stream.of(3, -2, 5, 8, -3, 10)
.filter(x -> x > 0)
.peek(x -> System.out.println("peeking " + x))
.filter(x -> x % 2 ==0);
System.out.println("Before collect");
List<Integer> integers = integerStream.collect(Collectors.toList());
System.out.println("After collect: " + integers);
- 코드만 보면 peek 메소드 내부에서 값을 출력한 뒤 "Before collect" 가 출력될 것 같지만 그렇지않다.
- "Before collect" 가 먼저 출력되고 peek 메소드 내부에 있는 출력문이 출력된다.
- 그 이유는 integerStream.collect(Collectors.toList()) 가 호출돼서 peek 이 사용되야겠다고 판단하기 때문이다. -> 결론은 stream 내부에 실행되는 행위가 최대한 뒤로 미뤄지는 것을 확인할 수 있다.
Curry
여러개의매개변수를받는함수를중첩된여러개의함수로쪼개어 매개변수를한번에받지않고여러단계에걸쳐나눠받을수있게 하는 기술이다.
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
- 위의 코드를 아래와 같이 바꿀 수 있다.
Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y;
IntStream
- stream.forEach 만을 사용하면 index 값을 사용하기 어렵다.
- 이렇때 IntStream 으로 해결할 수 있다.
IntStream.range(0, users.size()).forEach(i -> {
User user = users.get(i);
System.out.println("Do an operation on user " + user.getName() + " at index " + i);
});
REFERENCES
- 이승환님의 JAVA Stream
'Java' 카테고리의 다른 글
Method Reference (0) | 2022.03.06 |
---|---|
Collectors (JAVA STREAM) (0) | 2022.03.06 |
Stream 응용 (0) | 2022.03.06 |
함수형 인터페이스 (0) | 2022.02.26 |
제네릭 (0) | 2022.02.26 |