-
Stream(스트림) - 4. Optional<T> & OptionalIntJava 2020. 3. 10. 21:16반응형
Optional(JDK 1.8~)
Optional<T> : 제네릭 클래스로 "T타입의 객체"를 감싸는 래퍼 클래스, Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있음
public final class Optional<T> { private final T value; // T타입의 참조변수 ... }
최종 연산의 결과 타입이 Optional인 경우
최종 연산의 결과를 그냥 반환하는 것이 아닌 Optional 객체에 담아서 반환하는 것
객체에 담아서 반환하면, 반환한 결과가 null인지 체크하는 대신 Optional에 정의된 메서드를 통해서 간단히 처리할 수 있음
널 체크를 위한 if문 없이도 NullPointerException이 발생하지 않는 보다 간결하고 안전한 코드를 작성하는 것이 가능해짐
Object 클래스에 isNull(), nonNull(), requireNonNull()과 같은 메서드가 있는 것도 널 체크를 위한 if문을 메서드 안으로 넣어서 코드의 복잡도를 낮추기 위한 것
Optional 객체 생성
of() 또는 ofNullable()을 사용하여 생성함
String str = "abc"; Optional<String> optVal1 = Optional.of(str); Optional<String> optVal2 = Optional.of("abc"); Optional<String> optVal3 = Optional.of(new String("abc")); Optional<String> optVal4 = Optional.of(null); // NullPointerException 발생 Optional<String> optVal5 = Optional.ofNullable(null); // OK
기본값으로 초기화시 empty() 사용, null로 초기화할 수 있지만 empty()를 사용하는 것이 바람직함
- empty()는 제네릭 메서드라 앞에 <T>를 붙이지만, 추정 가능하므로 생략할 수 있음
Optional<String> optVal1 = null; // 널로 초기화 Optional<String> optVal2 = Optional.<String>empty(); // 빈 객체로 초기화 Optional<String> optVal3 = Optional.empty(); // 타입 추정 가능하므로 제네릭 생략 가능
Optional 객체의 값 가져오기
get() : Optional 객체의 값을 가져올 때 사용, null일 때는 NoSuchElementException이 발생
orElse() : get()과 비슷하지만, null일 때 대체할 값을 지정할 수 있음
Optional<String> optVal = Optional.of("abc"); String str1 = optVal.get(); // optVal에 저장된 값을 반환, null이면 예외 발생 String str2 = optVal.orElse(); // optVal에 저장된 값을 반환, null이면 "" 반환
orElseGet() : null을 대체할 값을 반환하는 람다식을 지정할 수 있음 (orElse()의 변형)
orElseThrow() : null일 때 지정한 예외를 발생시킴(orElse()의 변형)
T orElseGet(Supplier<? extends T> other) T orElseThrow(Supplier<? extends X> exceptionSupplier) String str3 = optVal.orElseGet(String::new); // () -> new String()과 동일 String str4 = optVal.orElseThrow(NullPointerException::new); // null이면 예외 발생
Stream처럼 Optional 객체도 filter(), map(), flatMap() 사용 가능 - Optional 객체 값이 null이라면 아무 일도 하지 않음
map()의 연산결과가 Optional<Optional<T>>일 때, flatMap()을 사용하면 Optional<T>를 결과로 얻음
int result = Optional.of("123") .filter(x -> x.length() > 0) .map(Integer::parseInt).orElse(-1); // result = 123 result = Optional.of("") .filter(x -> x.length() > 0) .map(Integer::parseInt).orElse(-1); // result = -1
parseInt()는 예외가 발생하기 쉬운 메서드
- 예외처리된 메서드를 만든다면?
static int optionalStringToInt(Optional<String> optionalString, int defaultValue) { try { return optionalString.map(Intger::parseInt).get(); } catch (Exception e) { return defaultValue; } }
isPresent() : Optional 객체의 값이 null이면 false, 아니면 true 반환
ifPresent(Consumer<T> block) : 값이 있으면 주어진 람다식을 실행, 없으면 아무 일도 하지 않음
/* 조건문 */ if(str != null) { System.out.println(str); } /* isPresent 이용하여 변경 */ if(Optional.ofNullable(str).isPresent()) { System.out.println(str); } /* ifPresent 이용하여 변경 */ Optional.ofNullable(str).ifPresent(System.out::println);
Optional<T>를 반환하는 Stream 클래스에 정의된 메서드 - ifPresent()와 잘 어울림
- max()와 min()은 rduce()를 이용해 작성된 것
Optional<T> findAny() Optional<T> findFirst() Optional<T> max(Comparator<? super T> comparator) Optional<T> min(Comparator<? super T> comparator) Optional<T> reduce(BinaryOperator<T> accumulator)
OptionalInt & OptionalLong & OptionalDouble
IntStream과 같은 기본형 스트림은 Optional도 기본형을 값으로 하는 OptionalInt, OptionalLong, OptionalDouble 반환
IntStream에 정의된 메서드 - 반환 타입이 Optional<T>가 아니라는 것을 제외하고는 Stream에 정의된 것과 비슷함
OptionalInt findAny() OptionalInt findFirst() OptionalInt reduce(IntBinaryOperator op) OptionalInt max() OptionalInt min() OptionalDouble average()
기본형 Optional에 저장된 값을 꺼낼 때 사용하는 메서드의 이름이 조금씩 다르다는 것에 주의
Optional<T> - T get() OptionalInt - int getAsInt() OptionalInt - long getAsLong() OptionalDouble - double getAsDouble()
OptionalInt 정의
public final class OptionalInt { ... private final boolean isPresent; // 값이 저장되어 있으면 true private final int value; // int 타입의 변수 ... }
기본형 int의 기본값은 0 = 아무런 값도 갖지 않는 OptionalInt에 저장된 값은 0, 0을 저장한 객체와는 같지 않음
OptionalInt opt1 = OptionalInt.of(0); // OptionalInt에 0 저장 OptionalInt opt2 = OptionalInt.empty(); // OptionalInt에 0 저장됨 - 기본값 0 System.out.println(opt1.isPresent()); // true - 0이 저장됨 System.out.println(opt2.isPresent()); // false - 값이 비어있음 System.out.println(opt1.getAsInt()); // 0 System.out.println(opt2.getAsInt()); // NoSuchElementException예외발생 System.out.println(opt1.equals(opt2)); // false
Optional객체의 경우 null 저장시 비어있는 것과 동일
Optional<String> opt1 = Optional.ofNullable(null); Optional<String> opt2 = Optional.empty(); System.out.println(opt.equals(opt2)); // true
반응형'Java' 카테고리의 다른 글
Stream(스트림) - 6. collect() (최종연산 2/3) (0) 2020.03.11 Stream(스트림) - 5. 최종 연산 1/3 (0) 2020.03.10 Stream(스트림) - 3. 스트림 중간 연산 (0) 2020.03.09 Stream(스트림) - 2. 스트림 생성하기 (0) 2020.02.13 Stream(스트림) - 1. 스트림이란 (0) 2020.02.13