int count = 0;
list.forEach(x -> count++); // 컴파일 오류: local variables referenced from a lambda expression must be final or effectively final람다는 변수의 값을 복사해 갖습니다. 바깥 변수를 바꿀 수 있게 하면 복사본과 원본이 어긋나므로 언어가 막습니다.
✅ 카운트는 스트림 연산으로, 정말 상태가 필요하면 AtomicInteger나 배열 한 칸을 씁니다.
long count = list.stream().filter(...).count();
// 또는
AtomicInteger count = new AtomicInteger();
list.forEach(x -> count.incrementAndGet());thenApply에 CompletableFuture를 돌려주는 함수를 넣음CompletableFuture<CompletableFuture<String>> nested = findUserId("kim").thenApply(Main::fetchEmail);
nested.join().join(); // 두 번 join해야 값이 나옴thenApply는 반환값을 그대로 감쌉니다. 비동기 함수를 이으면 Future<Future<T>>가 됩니다.
✅ thenCompose를 씁니다.
CompletableFuture<String> flat = findUserId("kim").thenCompose(Main::fetchEmail);computeIfAbsent로 메모이제이션static Map<Integer, Long> memo = new HashMap<>();
static long fib(int n) {
if (n < 2) return n;
return memo.computeIfAbsent(n, k -> fib(k - 1) + fib(k - 2)); // ConcurrentModificationException
}computeIfAbsent가 실행되는 동안 같은 맵을 재귀가 수정합니다. HashMap은 이를 감지해 예외를 던집니다.
✅ get으로 확인하고 계산 후 put합니다(패턴 14의 fib).
String v = valueOrDefault(cached, loadFromDb()); // cached가 있어도 DB를 읽음
Optional<String> o = ...;
o.orElse(loadFromDb()); // 값이 있어도 DB를 읽음인자는 메서드 호출 전에 평가됩니다. 비싼 기본값을 인자로 직접 넘기면 항상 실행됩니다.
✅ Supplier로 넘깁니다: valueOrDefault(cached, () -> loadFromDb()), o.orElseGet(() -> loadFromDb()).
andThen을 붙임Function<String, Integer> f = String::trim.andThen(String::length); // 컴파일 오류메서드 참조는 그 자체로 타입이 없습니다(target type이 정해져야 함). .andThen을 부를 수신 객체가 없습니다.
✅ 변수에 담거나 캐스팅합니다.
Function<String, String> trim = String::trim;
Function<String, Integer> f = trim.andThen(String::length);
// 또는 ((Function<String, String>) String::trim).andThen(String::length)thenCompose로 직렬 연결CompletableFuture<Integer> total = fetchPrice()
.thenCompose(p -> fetchShipping().thenApply(s -> p + s)); // 배송비 조회가 가격 조회 뒤에 시작배송비는 가격에 의존하지 않는데 thenCompose 안에서 만들면 가격이 끝나야 시작합니다. 두 작업 시간이 합산됩니다.
✅ 먼저 둘 다 시작하고 thenCombine으로 합칩니다.
CompletableFuture<Integer> price = fetchPrice();
CompletableFuture<Integer> shipping = fetchShipping();
CompletableFuture<Integer> total = price.thenCombine(shipping, Integer::sum);static T firstOr(List<T> list, T fallback) { ... } // 컴파일 오류: cannot find symbol T클래스가 제네릭이 아니면 메서드가 <T>를 직접 선언해야 합니다. 반환 타입 앞에 씁니다.
✅ static <T> T firstOr(List<T> list, T fallback).