List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));
//값이 있을수도 없을수도 있으므르 Optional 자료형으로 잡힌다
Optional<OnlineClass> spring = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("spring"))
.findFirst();
boolean present = spring.isPresent();
System.out.println(present); // true
Optional<OnlineClass> jpa = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
boolean presentJpa = jpa.isPresent();
System.out.println(presentJpa); //false
//아래와 같은 코드를 사용하면 Optional 값으로부터 값을 가져올수 있지만
//비어있는 옵셔널 값일지라도 수행하게 되므로 NoSuchElementException 오류가 발생할수 있다
OnlineClass onlineClass = spring.get();
System.out.println(onlineClass.getTitle());
//따라서 아래와 같이 수정을 해서 값이 있는지 확인을 하고 꺼내야 한다
if (jpa.isPresent()) {
OnlineClass jpaClass = jpa.get();
System.out.println(jpaClass.getTitle());
}
혹은, 다양한 Optional API를 활용해서 get()대신 다양한 메서드를 이용해서 처리할 수 있다
옵셔널에는 다양한 api가 존재
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(5, "rest api development", false));
//값이 있을수도 없을수도 있으므르 Optional 자료형으로 잡힌다
Optional<OnlineClass> springOptional = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("spring"))
.findFirst();
Optional<OnlineClass> jpaOptional = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
Optional.of()
Optional.ofNullable()
Optional.empty()
isPresent()
boolean presentSpring = springOptional.isPresent();
System.out.println(presentSpring); //true
boolean presentJpa = jpaOptional.isPresent();
System.out.println(presentJpa); //true
isEmpty() //자바 11부터 제공
get()
//아래와 같은 코드를 사용하면 Optional 값으로부터 값을 가져올수 있지만
//비어있는 옵셔널 값일지라도 수행하게 되므로 NoSuchElementException 오류가 발생할수 있다
OnlineClass onlineClass = springOptional.get();
System.out.println(onlineClass.getTitle());
//따라서 아래와 같이 수정을 해서 값이 있는지 확인을 하고 꺼내야 한다
if (jpaOptional.isPresent()) {
OnlineClass jpaClass = jpaOptional.get();
System.out.println(jpaClass.getTitle());
}
ifPresent(Consumer)
//옵셔널에 값이 들어있을때 무언가를 해야한다면
jpaOptional.ifPresent(oc -> System.out.println(oc.getTitle()));
springOptional.ifPresent(oc -> System.out.println(oc.getTitle()));
orElse(T)
//다양한 Optional API를 활용해서 get()대신 다양한 메서드를 이용해서 처리할 수 있다
OnlineClass jpaClass = jpaOptional.orElse(null);
//옵셔널 값을 가져오고 추가적인 행동을 할 경우
//값이 있든 없는 일단 createNewJapClass()코드는 실행이 된다 이후 전달의 차이
OnlineClass onelineClass = springOptional.orElse(createNewJpaClass());
OnlineClass onelineClass1 = jpaOptional.orElse(createNewJpaClass());
orElseGet(Supplier)
//옵셔널 값을 가져오고 추가적인 행동을 할 경우 orElseGet(서플라이어 사용 가능)
//값이 있는 경우에만 createNewJapClass() 실행
OnlineClass onlineClass4 = jpaOptional.orElseGet(()-> createNewJpaClass());
System.out.println(onlineClass4.getTitle());
//람다 표현식으로 전환 _ 메서드 레퍼런스 사용
jpaOptional.orElseGet(OptionalApiMain::createNewJpaClass);
springOptional.orElseGet(OptionalApiMain::createNewJpaClass);
orElseThrow()
//orElseThrow()
//없으면은 error를 던진다, 원하는 에러가있다면 지정할수 있다
OnlineClass onlineClass1 = springOptional.orElseThrow(()->{
return new IllegalArgumentException();
});
//람다 표현식으로 전환
OnlineClass onlineClass2 = springOptional.orElseThrow(IllegalAccessError::new);
System.out.println(onlineClass2.getTitle());
Optional filter(Predicate)
Optional<OnlineClass> onlineClass3 = jpaOptional
.filter(oc -> oc.getId() > 10);
System.out.println(onlineClass3); <- 필터의 조건에 맞지않아서 empty optional이 온 경우
//Optional.empty 출력
Optional<OnlineClass> onlineClass5 = springOptional
.filter(oc -> oc.getId() == 1);
onlineClass5.ifPresent(oc -> System.out.println(oc.getTitle()));
Optional map(Function)
Optional<Integer> springId = springOptional
.map(OnlineClass::getId);
springId.ifPresent(System.out::println); // map을 통해 id값만 가져온경우
Optional flatMap(Function) <- Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 용이
<flatMap 사용 전>
Optional<Optional<Progress>> progress = springOptional.map(OnlineClass::getProgress);
Optional<Progress> progress1 = progress.orElse(Optional.empty()); // <-값이 없으면 empty optional이 온다
<flatMap 사용 후>
// 현재 매핑해서 꺼내는 타입이 옵셔널일 경우 안에서 먼저 옵셔널을 벗겨내준다
// -> 두번 옵셔널을 벗겨내는 과정을 한번으로 줄여준다
Optional<Progress> progress2 = springOptional.flatMap(OnlineClass::getProgress);
//Progress progress0 = progress(1 or 2).orElseThrow();
//System.out.println(progress0.getStudyDuration());
참고로 stream()에서의 flatMap에서의 기능과는 다르다 -> stream에서는 1대1 매핑 목적이고, 옵셔널에서는 옵셔널인 값의 값으로 가져온 매핑값이 옵셔널일 경우 꺼내서 오는 방법으로 사용