[java] Optional.ifPresent ()의 적절한 사용

Java 8 ifPresent()에서 OptionalAPI 의 방법 을 이해하려고합니다 .

나는 간단한 논리가 있습니다.

Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));

그러나 이로 인해 컴파일 오류가 발생합니다.

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here)

물론 다음과 같이 할 수 있습니다.

if(user.isPresent())
{
  doSomethingWithUser(user.get());
}

그러나 이것은 정확히 어수선한 null수표 와 같습니다 .

코드를 다음과 같이 변경하면 :

 user.ifPresent(new Consumer<User>() {
            @Override public void accept(User user) {
                doSomethingWithUser(user.get());
            }
        });

코드가 더러워 져서 예전 null수표 로 돌아 가야한다고 생각하게합니다 .

어떤 아이디어?



답변

Optional<User>.ifPresent()Consumer<? super User>인수로 취합니다 . 유형이 void 인 표현식을 전달합니다. 그래서 그것은 컴파일되지 않습니다.

소비자는 람다 식으로 구현됩니다.

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

또는 메서드 참조를 사용하면 더 간단합니다.

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

이것은 기본적으로

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
    @Override
    public void accept(User theUser) {
        doSomethingWithUser(theUser);
    }
});

아이디어는 doSomethingWithUser()사용자가있는 경우에만 메서드 호출이 실행된다는 것입니다. 코드는 메서드 호출을 직접 실행하고 void 결과를에 전달하려고합니다 ifPresent().


답변

@JBNizet의 답변 외에도 일반적인 사용 사례 ifPresent는 다음 .isPresent().get()같이 결합하는 것입니다 .

이전 방식 :

Optional opt = getIntOptional();
if(opt.isPresent()) {
    Integer value = opt.get();
    // do something with value
}

새로운 방식:

Optional opt = getIntOptional();
opt.ifPresent(value -> {
    // do something with value
})

이것은 나에게 더 직관적입니다.


답변

간단하게 만들 수 있는데 왜 복잡한 코드를 작성합니까?

실제로 Optional클래스 를 절대적으로 사용하려는 경우 가장 간단한 코드는 이미 작성한 코드입니다.

if (user.isPresent())
{
    doSomethingWithUser(user.get());
}

이 코드는

  1. 읽을 수있는
  2. 디버그하기 쉬움 (중단 점)
  3. 까다 롭지 않다

Oracle이 OptionalJava 8에 클래스를 추가 했다고해서이 클래스가 모든 상황에서 사용되어야한다는 의미는 아닙니다.


답변

flatMap을 사용하십시오. 값이 있으면 flatMap은 해당 값만 포함하는 순차 Stream을 반환하고, 그렇지 않으면 빈 Stream을 반환합니다. 따라서 사용할 필요가 없습니다 ifPresent(). 예:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());


답변

다음과 같은 메서드 참조를 사용할 수 있습니다.

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

메소드 ifPresent()get Consumerobject as a paremeter and (from JavaDoc ) : “값이있는 경우 값으로 지정된 소비자를 호출합니다.” 가치는 귀하의 변수 user입니다.

또는이 메서드 doSomethingWithUserUser클래스에 있고 그렇지 않은 경우 다음 static과 같은 메서드 참조를 사용할 수 있습니다.

user.ifPresent(this::doSomethingWithUser);


답변