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;
}
public static void main(String[] args) {
List<String> words = Arrays.asList(args);
System.out.println(max(words));
}
결과
Exception in thread "main" java.lang.IllegalArgumentException: 빈 컬렉션
at item55.Main.max(Main.java:10)
at item55.Main.main(Main.java:23)
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); // 값이 든 옵셔널
}
public static void main(String[] args) {
List<String> words = Arrays.asList(args);
System.out.println(max(words));
}
결과
Optional.empty
Optional.of(value)에 null이 들어가면 NullPointerException을 던지니 주의
null 값도 허용하는 옵셔널을 만들려면 Optional.ofNullable(value) 사용
옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말것
옵셔널을 도입한 취지를 완전히 무시하는 행위
스트림의 종단 연산 중 상당수가 옵셔널을 반환
55-3. max를 스트림 버전으로 다시 작성
public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
return c.stream().max(Comparator.naturalOrder());
}
메서드가 특정 조건에서 값을 반환할 수 없을 때
Optional이란?
null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택해야 하는 기준
원하는 예외를 던질 수 있다.
항상 값이 채워져 있는 경우
기본값을 설정하는 비용이 큰 경우
Supplier<T>
를 인수로 받는) orElseGet을 사용하면, 값이 처음 필요할 때 Supplier를 사용해 생성하므로 초기 생성비용을 낮출 수 있음[참고] Optional 메서드 정리
Optional<T> filter(Predicate<T> predicate)
Optional<U> map(Funtion<? super T, ? extends U> f)
T orElseGet(Supplier<? extends T> supplier)
T orElseThrow(Supplier<? extends X> exceptionSupplier)
Optional 안티 패턴
컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸지 말것
Optional<List<T>>
를 반환하기 보다는 빈 ListOptional을 Map의 키나 값으로 사용하지 말자
정리