Java Optional 활용방법 요약

생성방법

  1. of()
    Option.of(someValue)
    someValue가 null 이면 NPE 발생

  2. ofNullable()
    Optional opt = Optional.ofNullable(someValue);
    someValue가 null이여도 Null 이 들어간 Optional이 생성됨

  3. empty()
    Optional opt = Optional.empty(); // Optional.ofNullable()와 동일

값 구하기

  1. get()
    opt.get();

값이 없을 땐 NoSuchElementException 발생

값 유무 확인

isPresent()
isEmpty() // 자바 11부터 생김

값이 있으면 하기

String result = opt.ifPresent(value -> doSome(value));

String result = opt.ifPresentOrElse(
value -> doSome(value), // 값이 있을 때 실행
() -> doOther() //값이 없을 때 실행
);

값이 없으면 다른 값 사용

String result = opt.orElse(“default”);

String result = opt.orElseGet(()->”defalut”); //orElse처럼 값이 없을 때 함수를 활용하여 새로운 값을 returen함

Option result = opt.or(()->Optional.of(“defalut”)); //opt 안에 값이 없을 때 optional을 리턴함

값이 없으면 익셉션, 있으면 값 리턴

Member m = opt.orElseThrow(()->new NoMemberExcetion());

map. 값이 없으면 빈 Optional 리턴

map에 전달받은 함수를 실행해서 값을 변환한 Optional 리턴, 값이 없으면 빈 Optional리턴
Optional birthOpt = memOpt.map(mem-> mem.getBirthday());
Optional pdOpt = memOpt.map(birth-> cal(birth));

Optional memOpt.map(mem-> mem.getBirthday()).map(birth-> cal(birth)); 형태로도 사용 가능

flatMap

flatMap에 전달한 함수가 Optional을 리턴할 때 사용한다,
여러겹의 Option을 벗겨낸다고 보면 됨.
아래 map, flatMap의 차이를 보자

Optional birthOpt = memOpt.flatMap(mem-> Optional.ofNullable(mem.getBirthday()));
Optional<Optional> birthOpt = memOpt.map(mem-> Optional.ofNullable(mem.getBirthday()));

filter

값을 충족하면 값 그대로 리턴하고 충족하지 않으면 빈 Optional 리턴

Optional filterd = strOpt.filter(str -> str.length() > 3);
filterd.ifPresent(str -> System.out.println(str));

두개 Optional 조합

1
2
3
4
5
6
Member m = ...;
if (m == null) return null;
Company c = getCompany(m);
if (c === null) return null;
Card card = createCard(m,c);
return card;

를 두개의 Optional로 짜보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Optional<Member> memOpt = ...;
Optional<Company> compOpt = memOpt.map(mem -> getCompany(mem));

Optional<Card> card = memOpt.flatMap(
mem -> compOpt.map(
comp -> createCard(mem, comp)
)
);



Optional<Member> memOpt = ...;
Optional<Card> compOpt = memOpt.flatMap(
mem -> {
Optional<Company> compOpt = getCompanyOptional(mem));
return compOpt.map(comp -> createCard(mem, comp));
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Member m1 = ...;
Member m2 = ...;

if (m1 == null && m2 == null)
return null;

if (m1 == null)
return m2 ;

if (m2 == null)
return m1 ;

return m1.year > m2.year ? m1 : m2;

를 두개의 Optional로 짜보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Optional<Member> mem1Opt = ...;
Optional<Member> mem2Opt = ...;

Optional<Member> result =
mem1Opt.flatMap(m1 -> ...) // m1이 있으면
.or(()->mem2Opt); // map 결과가 없으면 m2 사용


Optional<Member> result =
mem1Opt.flatMap(m1 -> { // m1이 있으면
return mem2Opt.map(m2 -> { //m2가 있으면
return m1.year > m2.year ? m1 : m2
}).orElse(m1); //m2가 없으면 m1
})
.or( ()-> m2); // flatMap 결과가 없으면 m2 사용

return result.orElse(null);

ifPresent를 사용하면 null 사용할 때와 유사한 구조가 된다.
대신 map, flatMap, filter, orElse, or, ifPresent등 익숙해지자

Share