티스토리 뷰

Java

[Java8] Optional 소개 및 API

먹태 2021. 7. 18. 17:24

 

Optional : 오직 값 한 개가 들어 있을수도, 없을 수도 있는 컨테이너

 

 

ex ) 자바 프로그래밍에서 NulllPointException을 보게 될 때가 있다

package java8study;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class App3 {

    public static void main(String[] args) {
        List<OnlineClass> springClasses = new ArrayList<>();
        springClasses.add(new OnlineClass(1, "spring boot", true));
        springClasses.add(new OnlineClass(2, "spring data jpa", true));
        springClasses.add(new OnlineClass(3, "spring mvc", false));
        springClasses.add(new OnlineClass(4, "spring core", false));
        springClasses.add(new OnlineClass(5, "rest api development", false));

        OnlineClass springBoot =  new OnlineClass(1, "spring boot", true);
        Duration studyDuration = springBoot.getProcess().getStudyDuration(); 
        System.out.println("studyDuration :" + studyDuration);

    }
}

 

이럴경우 보통

 Progress progress = springBoot.getProcess();
        if(progress !=null){
            System.out.println(progress.getStudyDuration());
        }
    public Progress getProcess() {
        if(this.process == null){
            throw new IllegalStateException();
        }
        return process;
    }

이런 두가지 방식으로 처리를 하는데 Optional을 이럴때 쓰면 더 명시적으로 정리가 됨

 

 

주의점

- 리턴 타입으로만 쓰기를 권장

- Optional을 리턴하는 메소드에서 null을 리턴하지말자 -> optional을 쓰는 이유가 없어짐

- 프리미티브 타입용 Optional이 따로 있다 ex) Optionalint, OptionalLong ....

- Collection, Map, Stream Array, Optional은 Optional로 감싸지 말것 -> 이 자체만으로도 비어있는지 판단할수 있는 인스턴스들

 

 

 

 

 

isPresent() : Optional에 값이 있는지 없는지 확인 

package java8study;

import com.fasterxml.jackson.core.JsonToken;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class App3 {

    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("jpa"))
                .findFirst();
                
        boolean present = optional.isPresent();
        System.out.println(present);
    }
}

- 변수를 추출해줄때 "jpa"으로 시작되는게 있을수도 있고, 없을수도 있어서 알아서 Optional로 선언해준다

 

 

 

 

 

Optional에 있는 값 가져오기

optional.get()을 쓰면 되는데 값이 없을 경우

오류뜸

 

 

 

이럴때 쓰는것들

 

ifPresent() : 값이 있는경우 그 값을 가지고 ~~~ 하라

  optional.ifPresent(oc->{
            System.out.println(oc.getTitle());
        });

값이 있으면 제목을 출력하라

 

 

 

orElse(), orElseGet() :  있으면 가져오고 없을경우 ~~~을 하라 

package java8study;

import com.fasterxml.jackson.core.JsonToken;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class App3 {

    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("jap"))
                .findFirst();


			OnlineClass onlineClass = optional.orElse(createNewClass());

			OnlineClass onlineClass2 = optional.orElseGet(()->createNewClass());
    }

    private static OnlineClass createNewClass() {
        System.out.println("creating new online class");
        return new OnlineClass(10,"new class", false);
    }
}

 

- 값이 있으면 가져오고 없으면 createNewClass 실행하라

- 근데 orElse같은 경우에는 값이 있어도 createNewClass가 실행 되기때문에 orElseGet을 쓰는게 더 좋을듯?

 

 

 

.orElseThrow() : 값이 있는 경우 가져오고 없는 경우 에러를 던져라

  OnlineClass onlineClass = optional.orElseThrow(()->{
            return new IllegalStateException();
        });

 

 

 

 

 

Optional에 있는 값 걸러내기

Optional<OnlineClass> onlineClass =optional.filter(oc->!oc.isClosed());
System.out.println(onlineClass.isEmpty());

 

- 필터에 값이 해당 안되면 비어있는 optional이 나온다

 

 

 

 

 

Optional 형태 변환

Optional<Optional<Progress>> progress = optional.map(OnlineClass::getProcess);
Optional<Progress> progress1 = progress.orElse(Optional.empty());

Optional<Progress> progress2 = optional.flatMap(OnlineClass::getProcess);

 - Map일때 flatMap을 사용하면 편리하게 꺼낼수 있음

 

 

 

 

 

참고

OnlineClass.java

package java8study;

public class OnlineClass {
    private Integer id;
    private String title;
    private boolean closed;
    private Progress process;

    public OnlineClass(Integer id, String title, boolean closed) {
        this.id = id;
        this.title = title;
        this.closed = closed;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isClosed() {
        return closed;
    }

    public void setClosed(boolean closed) {
        this.closed = closed;
    }

    public Progress getProcess() {
        ////
        if(this.process == null){
            throw new IllegalStateException();
        }

        return process;
    }

    public void setProcess(Progress process) {
        this.process = process;
    }
}

 

 

 

Progress.jasva

package java8study;

import java.time.Duration;

public class Progress {

    private Duration studyDuration;

    private boolean finished;

    public Duration getStudyDuration() {
        return studyDuration;
    }

    public void setStudyDuration(Duration studyDuration) {
        this.studyDuration = studyDuration;
    }
}

 

 

 

강의 : 인프런 더 자바, Java8

댓글
최근에 올라온 글
최근에 달린 댓글
링크
Total
Today
Yesterday