코드 55-1 컬렉션에서 최댓값을 구한다(컬렉션이 비어있으면 예외를 던진다)
public static <E extends Comparable<E>> E max (Collection<E> c) {
if(c.isEmpty())
throw new IllegalArgumentException("빈 컬렉션");
E result = null;
for (E e : c )
if (result==null || e.compareTo(result) > 0)
result = Objects.requireNonNull(e);
return result;
}
코드 55-2 컬렉션에서 최댓값을 구해 Optional로 반환한다.
public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
if (c.isEmpty())
return Optional.empty();
E result = null;
for (E e : c)
if(result==null||e.compareTo(result) > 0)
result = Objects.requireNonNull(e);
return Optional.of(result);
}
코드 55-3 컬렉션에서 최댓값을 구해 Optional로 반환한다 - 스트림 버젼
public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
return c.stream().max(Comparator.naturalOrder());
}
그렇다면 null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택해야 하는 기준은 무엇인가?
옵셔널은 검사 예외와 취지가 비슷하다(아이템 71) 즉, 반환값이 없을 수도 있음을 API 사용자에게 명확하게 알려주어야 한다.
코드 55-4 옵셔널 활용1 - orElse : 기본값을 정해둘 수 있다
String lastWordInLexicon = max(words).orElse("단어 없음...");
코드 55-5 옵셔널 활용2 - orElseThrow : 원하는 예외를 던질 수 있다
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
코드 55-6 옵셔널 활용 3 - get : 항상 값이 채워져 있다고 가정한다
Element lastNobleGas = max(Elements.NOBLE_GASES).get();
이외에 이따금 기본값을 설정하는 비용이 아주 커서 부담이 되면, Supplier를 인수로 받는 orElseGet을 사용하면 값이 처음 필요할 때 Supplier를 사용해 생성하므로 초기 설정 비용을 낮출 수 있다.
이외에 filter, map, flatMap, ifPresent 메서드가 있다.
Optional<ProcessHandle> parentProcess = ph.parent();
System.out.println("부모 PID:" + (parentProcess.isPresent() ?
String.valueOf(parentProcess.get().pid()) : "N/A"));
이 코드는 Optional의 map을 사용하여 다음처럼 다듬을 수 있다.
System.out.println("부모 PID:" +
ph.parent().map(h-> String.valueOf(h.pid))).orElse("N/A");
스트림을 사용한다면 옵셔널들을 Stream<Optional>로 받아서, 그 중 채워진 옵셔널들에서 값을 뽑아 Stream에 건네 담아 처리하는 경우가 드물지 않다.
streamOfOptionals
.filter(Optional::isPresnet)
.map(Optional::get)
Optional에 값이 있다면, 그 값을 꺼내서 스트림에 매핑한다.
자바 9에서는 Optional에 stream() 메서드가 추가되었다. 이 메서드는 Optional을 Stream으로 변환해주는 어댑터다. 옵셔널에 값이 있으면 그 값을 원소로 담은 스트림으로, 값이 없다면 빈 스트림으로 변환한다.
streamOfOptionals
.flatMap(Optional::stream)
성능 이슈