Programming/Java

[Java] Optional API

rw- 2023. 4. 9. 17:48
728x90

11. Optional API

Optional 만들기

  • Optional.of()
    value가 null인 경우 NullPointerException을 던집니다. 반드시 값이 있어야 하는 객체인 경우 해당 메서드를 사용하면 됩니다.
Throws: NullPointerException – if value is null
public static <T> Optional<T> of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
        }

Optional<String> optional = Optional.of("String");
  • Optional.ofNuallable()
    value가 null인 경우 비어있는 Optional을 반환합니다. 값이 null일수도 있는 것은 해당 메서드를 사용하면 됩니다.
public static <T> Optional<T> ofNullable(T value) {
    return value == null ? (Optional<T>) EMPTY
    : new Optional<>(value);
    }

Optional<String> optional = Optional.ofNuallable(null);
  • Optional.empty()
    비어있는 Optional 객체를 생성합니다. 조건에 따라 분기를 태워야 하고 반환할 값이 없는 경우에도 사용합니다.
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
        }

Optional<String> optional = Optional.empty();

Optional에 값이 있는지 없는지 확인하기

  • isPresent()
    값이 있으면 true를 반환하고 그렇지 않으면 false를 반환합니다.
  • isEmpty() (Java 11부터 제공)
    값이 없으면 true를 반환하고 그렇지 않으면 false를 반환합니다.
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));

Optional<OnlineClass> optional = springClasses.stream()
    .filter(oc -> oc.getTitle().startsWith("jpa"))
    .findFirst();

boolean present = optional.isPresent();
boolean empty = optional.isEmpty();

/*
present = false
empty = true
*/

Optional에 있는 값 가져오기

  • get()
  • 만약 비어있는 Optional에서 무언가를 꺼낸다면??
String title = optional.get().getTitle();
System.out.println("title = " + title);

//title = spring boot

//비어있는 경우
Exception in thread "main" java.util.NoSuchElementException: No value present

Optional에 값이 있는 경우에 그 값을 가지고 ~~를 하라.

  • ifPresent(Consumer)
  • 예) Spring으로 시작하는 수업이 있으면 id를 출력하라.
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));

Optional<OnlineClass> optional = springClasses.stream()
    .filter(oc -> oc.getTitle().startsWith("jpa"))
    .findFirst();

// if 문으로 체크할 필요없이 optional.ifPresent() 메서드를 사용할 수 있다.
optional.ifPresent(oc -> {
  System.out.println("oc.getTitle() = " + oc.getTitle());
});

//oc.getTitle() = spring boot

Optional에 값이 있으면 가져오고 없는 경우에 ~~를 리턴하라.

  • orElse(T)
  • 예) JPA로 시작하는 수업이 없다면 비어있는 수업을 리턴하라.
    최종적으로 연산을 끝낸 후에도 옵셔널 객체가 비어있다면 기본값으로 제공할 객체를 지정합니다.
    비어있든 비어있지 않든 createNewJpaClass()메서드 항상 리턴
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));

Optional<OnlineClass> optional = springClasses.stream()
    .filter(oc -> oc.getTitle().startsWith("jpa"))
    .findFirst();

OnlineClass onlineClass = optional.orElse(createNewJpaClass());
System.out.println("onlineClass = " + onlineClass.getTitle());

//jpa로 시작하는 수업이 있을 때
//creating new online class
//onlineClass = New class

//jpa로 시작하는 수업이 없을 때
//creating new online class
//onlineClass = spring boot

Optional에 값이 있으면 가져오고 없는 경우에 ~~를 하라.

  • orElseGet(SUpplier)
  • 예) JPA로 시작하는 수업이 없다면 새로 만들어서 리턴하라.
    최종적으로 연산을 끝낸 후에도 옵셔널 객체가 비어있다면 기본값으로 제공할 공급자 함수Supplier를 지정합니다.
    값이 없는 경우에만 실행(App::createNewJpaClass)
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));

Optional<OnlineClass> optional = springClasses.stream()
    .filter(oc -> oc.getTitle().startsWith("jpa"))
    .findFirst();

OnlineClass onlineClass2 = optional.orElseGet(App::createNewJpaClass);
System.out.println("onlineClass2 = " + onlineClass2.getTitle());

//jpa로 시작하는 수업이 있을 때
//onlineClass2 = jpa boot

//jpa로 시작하는 수업이 없을 때
//creating new online class
//onlineClass2 = New class

Optional에 값이 있으면 가져오고 없는 경우 에러를 던져라.

  • orElseThrow()
OnlineClass onlineClass3 = optional.orElseThrow();
System.out.println("onlineClass3 = " + onlineClass3.getTitle());

OnlineClass onlineClass3_1 = optional.orElseThrow(() -> {
  return new IllegalArgumentException();
});
System.out.println("onlineClass3 = " + onlineClass3_1.getTitle());

OnlineClass onlineClass3_2 = optional.orElseThrow(IllegalArgumentException::new);
System.out.println("onlineClass3 = " + onlineClass3_2.getTitle());

Optional에 들어있는 값 걸러내기

  • Optional filter(Predicate)
    predicate 값이 참이면 해당 필터를 통과시키고 거짓이면 통과 되지 않습니다.
Optional<OnlineClass> onlineClass_filter = optional
    .filter(oc -> !oc.isClosed());
System.out.println("onlineClass_filter.isEmpty() = " + onlineClass_filter.isEmpty());
System.out.println("onlineClass_filter.isPresent() = " + onlineClass_filter.isPresent());

//onlineClass_filter.isEmpty() = true
//onlineClass_filter.isPresent() = false

Optional에 들어있는 값 변환하기

  • Optional map(Function)
  • Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 편리하다.
Optional<Integer> integer = optional.map(OnlineClass::getId);
System.out.println("integer = " + integer.isPresent());


Optional<Progress> progress = optional.flatMap(OnlineClass::getProgress);

Optional<Optional<Progress>> progress1 = optional.map(OnlineClass::getProgress);
Optional<Progress> progress2 = progress1.orElse(Optional.empty());

//integer = true

참조

728x90
반응형