인프런 더 자바, Java 8 - 백기선 강의를 듣고 정리한 내용
오직 값 한개가 들어올 수도 없을 수도 있는 컨테이너. (래퍼 클래스)
NullPointerException을 보게 되는 이유?
메소드 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택 방법
String str = "apple";
Optional<String> opt1 = Optional.of(str);
Optional<String> opt2 = Optional.ofNullable(str);
Optional<String> opt3 = Optional.empty();
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("spring"))
.findFirst();
boolean present = optional.isPresent();
스트림을 사용하여 제목이 "spring"으로 시작하는 것을 filter하고
그 중 첫번째로 나온것을 반환하는데 이 때 반환타입이 Optional이다.
필터된 값이 있을 수도 없을 수도 있기 때문이다.
isPresent() : 반환된 값이 존재하는지 확인한다.
isEmpty() : 반대로 반환된 값이 존재하지 않는지 확인한다.
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("spring"))
.findFirst();
OnlineClass onlineClass = optional.get();
Optional에 있는 값을 가져오려면 get()을 이용한다.
startsWith("java")인 경우, Optional은 "java"로 시작하는 값이 없기 때문에
빈 값을 갖고 있을텐데 비어있는 Optional에 get()을 하면?
→ NoSuchElementException 발생!!!
뒤이어 나올 다른 API를 통해서 위의 문제 상황을 처리할 수 있다.
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("spring"))
.findFirst();
optional.ifPresent(oc -> System.out.println(oc.getTitle()));
ifPresent는 Optional에 값이 있는 경우 특정 처리를 할 수 있게 한다.
특정 처리와 관련된 내용은 Consumer 함수형 인터페이스 람다식으로 작성.
public class App {
public static void main(String[] args) {
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("java"))
.findFirst();
OnlineClass onlineClass = optional.orElse(createNewClass());
System.out.println(onlineClass.getTitle());
}
private static OnlineClass createNewClass() {
System.out.println("creating new class");
return new OnlineClass(10, "new class", false);
}
}
public class App {
public static void main(String[] args) {
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("spring"))
.findFirst();
OnlineClass onlineClass = optional.orElseGet(App::createNewClass);
System.out.println(onlineClass.getTitle());
}
private static OnlineClass createNewClass() {
System.out.println("creating new class");
return new OnlineClass(10, "new class", 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();
OnlineClass onlineClass = optional.orElseThrow();
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("spring"))
.findFirst();
Optional<OnlineClass> optional2 = optional.filter(OnlineClass::isClosed);
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("spring"))
.findFirst();
Optional<Integer> optional2 = optional.map(OnlineClass::getId);
map()을 이용하여 optional에 들어있는 값을 변환할 수 있다.
예제의 타입이 OnlineClass → Integer로 바뀐것을 확인할 수 있다.
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("spring"))
.findFirst();
// map
Optional<Optional<Progress>> progress = optional.map(OnlineClass::getProgress);
Optional<Progress> progress1= progress.orElse(Optional.empty());
// flatMap
Optional<Progress> progress2 = optional.flatMap(OnlineClass::getProgress);
flatMap의 경우 Optional안에 들어있는 인스턴스가 Optional인 경우 사용하면 편리한 api이다.
flatMap을 사용하면 map을 사용할 경우보다 작업 단계가 한 단계 더 줄어든다고 보면 된다.
OptionalInt optionalInt = OptionalInt.of(10);
OptionalInt optionalInt1 = OptionalInt.empty();
System.out.println(optionalInt.isPresent());
System.out.println(optionalInt1.isPresent());
System.out.println(optionalInt.getAsInt());
Optional.empty()
를 사용하자.