Optional API

구름코딩·2020년 10월 5일
0

java8 _ 더 자바

목록 보기
11/23

Optioanal 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> 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

옵셔널값을 가져오는 방법

  • 단순한 get() 메서드 사용
//아래와 같은 코드를 사용하면 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활용하여 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(), isEmpty()

isPresent()

boolean presentSpring = springOptional.isPresent();
System.out.println(presentSpring); //true

boolean presentJpa = jpaOptional.isPresent();
System.out.println(presentJpa); //true
isEmpty() //자바 11부터 제공

옵셔널에 있는 값 가져오기 _ get() (존재유뮤 상관x)

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)

ifPresent(Consumer)

//옵셔널에 값이 들어있을때 무언가를 해야한다면
jpaOptional.ifPresent(oc -> System.out.println(oc.getTitle()));
springOptional.ifPresent(oc -> System.out.println(oc.getTitle()));

옵셔널에 값이 있으면 가져오고 없는 경우 ~를 리턴 _ orElse(T)

orElse(T)

//다양한 Optional API를 활용해서 get()대신 다양한 메서드를 이용해서 처리할 수 있다
OnlineClass jpaClass = jpaOptional.orElse(null);

//옵셔널 값을 가져오고 추가적인 행동을 할 경우
//값이 있든 없는 일단 createNewJapClass()코드는 실행이 된다 이후 전달의 차이
OnlineClass onelineClass = springOptional.orElse(createNewJpaClass());
OnlineClass onelineClass1 = jpaOptional.orElse(createNewJpaClass());

옵셔널에 값이 있으면 가져오고 없는 경우 ~를 수행 _ orElseGet(Supplier)

orElseGet(Supplier)

//옵셔널 값을 가져오고 추가적인 행동을 할 경우 orElseGet(서플라이어 사용 가능)
//값이 있는 경우에만 createNewJapClass() 실행
OnlineClass onlineClass4 = jpaOptional.orElseGet(()-> createNewJpaClass());
System.out.println(onlineClass4.getTitle());

//람다 표현식으로 전환 _ 메서드 레퍼런스 사용
jpaOptional.orElseGet(OptionalApiMain::createNewJpaClass);
springOptional.orElseGet(OptionalApiMain::createNewJpaClass);

옵셔널에 값이 있으면 가져오고 없는 경우 에러를 발생 _ orElseThrow()

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 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()));

옵셔널에 들어있는 값 변환하기 _ map(Function), flatMap(Function)

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 매핑 목적이고, 옵셔널에서는 옵셔널인 값의 값으로 가져온 매핑값이 옵셔널일 경우 꺼내서 오는 방법으로 사용

profile
내꿈은 숲속의잠자는공주

0개의 댓글