티스토리 뷰

Java

JAVA, Optional

hwangyoungjae 2021. 12. 10. 12:12
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. Optional 객체 생성하기

1.1 Optional.of - 참조변수의 값이 null이 아닐때

Optional<String> optStr = Optional.of("Hello World!");
Optional<String> optStNull = Optional.of(null); // NullPointerException 발생

`of`로 Optional 객체를 생성할때 null을 인자로 사용하면 NullPointerException이 발생하기 때문에 반드시 값이 있어야 한다.

1.2 Optional.ofNullable - 참조변수의 값이 null일 가능성이 있을때

Optional<String> optStr = Optional.ofNullable("Hello World!");
Optional<String> optStrN = Optional.ofNullable(null);
System.out.printf("optStr : Present=%s, Empty=%s%n", optStr.isPresent(), optStr.isEmpty());
System.out.printf("optStrN: Present=%s, Empty=%s%n", optStrN.isPresent(), optStrN.isEmpty());

// 출력
optStr : Present=true, Empty=false
optStrN: Present=false, Empty=true

1.3 Optional.empty - 참조변수를 기본값(null)로 초기화할때

Optional<String> optStrN = Optional.empty();
System.out.printf("optStrN: Present=%s, Empty=%s%n", optStrN.isPresent(), optStrN.isEmpty());
        
// 출력
optStrN: Present=false, Empty=true

2. Optional 객체의 값 가져오기

2.1 T get() - 참조변수가 반드시 있을때

Optional<String> optStr = Optional.of("Hello World");
Optional<String> optStrN = Optional.empty();
String s1 = optStr.get();
String s2 = optStrN.get(); // NoSuchElementException 발생

2.2 T orElse(T other) - 참조변수가 없을때 값 대체

Optional<String> optStr = Optional.of("Hello World");
Optional<String> optStrN = Optional.empty();
System.out.println("optStr : " + optStr.orElse("Default value"));
System.out.println("optStrN: " + optStrN.orElse("Default value!"));

// 출력
optStr : Hello World
optStrN: Default value!

2.3 T orElseGet(Supplier<? extends T> supplier) - 참조변수가 없을때 람다식으로 대체

Optional<String> optStr = Optional.of("Hello World");
Optional<String> optStrN = Optional.empty();
System.out.println("optStr : " + optStr.orElseGet(() -> "Default value"));
System.out.println("optStrN: " + optStrN.orElseGet(() -> "Default value"));

// 출력
optStr : Hello World
optStrN: Default value

 

2.4 T orElseThrow(Supplier<? extends X> exceptionSupplier) - 참조변수가 null일때 예외 발생

Optional<String> optStr = Optional.of("Hello World");
Optional<String> optStrN = Optional.empty();
optStr.orElseThrow(IllegalStateException::new);
optStrN.orElseThrow(IllegalStateException::new); // IllegalStateException 발생

2.5 Optional<T> filter(Predicate<? super T> predicate) - 필터링해서 참조변수 가져오기

Optional<String> optStr1 = Optional.of("Hello World");
Optional<String> optStr2 = Optional.of("World Hello");
String s1 = optStr1.filter(s -> s.substring(0, 1).equals("H")).orElse("Default");
String s2 = optStr2.filter(s -> s.substring(0, 1).equals("H")).orElse("Default");
System.out.println("s1: " + s1);
System.out.println("s2: " + s2);

// 출력
s1: Hello World
s2: Default

2.6 boolean isPresent() - 참조변수 확인

Optional<String> optStr1 = Optional.ofNullable("youngjae");
Optional<String> optStr2 = Optional.ofNullable(null);

System.out.println("optStr1.isPresent() = " + optStr1.isPresent());
System.out.println("optStr2.isPresent() = " + optStr2.isPresent());

// 출력
optStr1.isPresent() = true
optStr2.isPresent() = false

2.7 void ifPresent(Consumer<? super T> action) - 참조변수 있으면 actino 호출

Optional<String> optStr1 = Optional.ofNullable("youngjae");
Optional<String> optStr2 = Optional.ofNullable(null);

optStr1.ifPresent(s -> System.out.println("optStr1: " + s));
optStr2.ifPresent(s -> System.out.println("optStr2: " + s));

// 출력
optStr1: youngjae

 

2.8 void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) - 참조변수 있으면 action, 없으면 emptyActino 호출

Optional<String> optStr1 = Optional.ofNullable("youngjae");
Optional<String> optStr2 = Optional.ofNullable(null);

optStr1.ifPresentOrElse(
        s -> System.out.println("optStr1: " + s),
        () -> System.out.println("optStr1: novalue"));
optStr2.ifPresentOrElse(
        s -> System.out.println("optStr2: " + s),
        () -> System.out.println("optStr2: novalue"));
    }

// 출력
optStr1: youngjae
optStr2: novalue

 

2.9 Optional<U> map(Function<? super T, ? extends U> mapper) - 매핑

Optional<String> optStr1 = Optional.of("Hello World");
Optional<String> optStr2 = Optional.empty();
Integer s1 = optStr1.map(String::length).orElse(0);
Integer s2 = optStr2.map(String::length).orElse(0);
System.out.println("s1: " + s1);
System.out.println("s2: " + s2);

// 출력
s1: 11
s2: 0

2.10 Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) - 리턴타입 Optional

map과 flatMap의 차이점을 보면서 flatMap의 특성을 살펴보겠음

map과 flatMap은 반환타입이 Optional인건 같지만, map은 람다식 return값을 Optional로 감싸서 주지만, flatMap은 직접 감싸야 한다 혹은 이미 감싸져 있는걸 그대로 사용할수 있다.

Member 객체에 getName이 Optinal타입으로 return해줄때 member의 name을 가져오는 예제를 가지고 비교해보자.

JPA에서 비식별 형태로 연관관계를 구성할때 Optional을 구성하고, 이때 flatMap을 통해 활용할수 있을것으로 생각된다.

 

예제에 사용된 Member class

public class Member {
    private String name = null;

    public Member() {
    }

    public Member(String name) {
        this.name = name;
    }

    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }
}
Member m1 = new Member();
Member m2 = new Member("youngjae");
Optional<Member> optM1 = Optional.ofNullable(m1);
Optional<Member> optM2 = Optional.ofNullable(m2);

// map
String m1Name = optM1
        .map(member -> member.getName().orElse("noname"))
        .get();
String m2Name = optM2
        .map(member -> member.getName().orElse("noname"))
        .get();
System.out.println("map    , m1Name: " + m1Name);
System.out.println("map    , m2Name: " + m2Name);


// flatMap
String m1NameF = optM1
        .flatMap(Member::getName)
        .orElse("noname");
String m2NameF = optM2
        .flatMap(Member::getName)
        .orElse("noname");
System.out.println("flatMap, m1Name: " + m1NameF);
System.out.println("flatMap, m2Name: " + m2NameF);

map을 사용한 부분은 억지를 부린감이 없지않아 있지만, 어쨌든 flatMap을 사용하면 깔끔해진다.

 

 

 

참고: 

자바의 정석 3판

https://mangkyu.tistory.com/70

https://madplay.github.io/post/difference-between-map-and-flatmap-methods-in-java

https://ryanwoo.tistory.com/48

'Java' 카테고리의 다른 글

JPA, OneToMany, FetchType, fetch join+distinct  (0) 2021.12.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함