record Product(String sku, String name, Integer discountRate) 에서 discountRate 는 null 일 수 있습니다(할인 없음).
Map<String, Product> catalog 에서 SKU 로 조회해 할인율이 있고 10% 이상이면 "name (rate%)", 할인이 없거나 10% 미만이면 "name", 상품이 없으면 "unknown sku" 를 반환하는 describe(String sku) 를 Optional 체인으로 작성하세요.
isPresent/get 을 쓰지 마세요.
import java.util.*;
public class Ex1 {
record Product(String sku, String name, Integer discountRate) {}
static final Map<String, Product> CATALOG = Map.of(
"P1", new Product("P1", "Keyboard", 15),
"P2", new Product("P2", "Mouse", 5),
"P3", new Product("P3", "Monitor", null));
static String describe(String sku) {
return Optional.ofNullable(CATALOG.get(sku))
.map(p -> Optional.ofNullable(p.discountRate())
.filter(r -> r >= 10)
.map(r -> p.name() + " (" + r + "%)")
.orElse(p.name()))
.orElse("unknown sku");
}
public static void main(String[] args) {
for (String sku : List.of("P1", "P2", "P3", "P9")) System.out.println(sku + " → " + describe(sku));
}
}
// 출력:
// P1 → Keyboard (15%)
// P2 → Mouse
// P3 → Monitor
// P9 → unknown skuorElse 와 orElseGet 의 차이를 이용한 버그를 찾아 고치세요. 아래 SessionCache.get 은 캐시 히트 시에도 createSession 이 호출됩니다. 호출 횟수를 세어 수정 전후를 비교하는 코드를 작성하세요.
Map<String, String> cache = new HashMap<>();
int created = 0;
String get(String userId) {
return Optional.ofNullable(cache.get(userId)).orElse(createSession(userId));
}import java.util.*;
public class Ex2 {
static final Map<String, String> cache = new HashMap<>();
static int created = 0;
static String createSession(String userId) { created++; String s = "sess-" + userId; cache.put(userId, s); return s; }
static String getBuggy(String userId) {
return Optional.ofNullable(cache.get(userId)).orElse(createSession(userId)); // 항상 생성
}
static String getFixed(String userId) {
return Optional.ofNullable(cache.get(userId)).orElseGet(() -> createSession(userId)); // 미스 때만 생성
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) getBuggy("kim");
System.out.println("buggy: created = " + created); // 3 (매번 생성)
created = 0; cache.clear();
for (int i = 0; i < 3; i++) getFixed("kim");
System.out.println("fixed: created = " + created); // 1
}
}
// 출력:
// buggy: created = 3
// fixed: created = 1문자열 목록 ["42", "x", "", "7", null, "100"] 에서 정수로 파싱 가능한 것만 골라 합계를 구하세요. Optional<Integer> parse(String s) 를 만들고(null/빈 문자열/숫자 아님 → empty), 스트림에서 flatMap(Optional::stream) 으로 합치세요. 그리고 같은 목록의 첫 번째 파싱 가능한 값을 findFirst 로 구해 출력하세요.
import java.util.*;
public class Ex3 {
static Optional<Integer> parse(String s) {
return Optional.ofNullable(s)
.map(String::strip)
.filter(t -> !t.isEmpty() && t.matches("-?\\d+"))
.map(Integer::valueOf);
}
public static void main(String[] args) {
List<String> raw = Arrays.asList("42", "x", "", "7", null, "100");
int sum = raw.stream().map(Ex3::parse).flatMap(Optional::stream).mapToInt(Integer::intValue).sum();
System.out.println("sum = " + sum);
Optional<Integer> first = raw.stream().map(Ex3::parse).flatMap(Optional::stream).findFirst();
System.out.println("first = " + first.orElse(-1));
System.out.println("parse(null) = " + parse(null) + ", parse(\"x\") = " + parse("x"));
}
}
// 출력:
// sum = 149
// first = 42
// parse(null) = Optional.empty, parse("x") = Optional.empty