[java] 옵션이없는 경우 로직을 실행하는 방법은 무엇입니까?

java8을 사용하여 다음 코드를 바꾸고 싶습니다 Optional.

public Obj getObjectFromDB() {
    Obj obj = dao.find();
    if (obj != null) {
        obj.setAvailable(true);
    } else {
        logger.fatal("Object not available");
    }

    return obj;
}

다음 의사 코드는 orElseRun방법 이 없기 때문에 작동하지 않지만 어쨌든 내 목적을 보여줍니다.

public Optional<Obj> getObjectFromDB() {
    Optional<Obj> obj = dao.find();
    return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}



답변

Java 9 이상을 사용하면 다음과 같이 ifPresentOrElse할 수 있습니다.

Optional<> opt = dao.find();

opt.ifPresentOrElse(obj -> obj.setAvailable(true),
                    () -> logger.error("…"));

vavr 등을 사용하여 커링 하면 더 깔끔한 코드를 얻을 수 있지만 아직 시도하지 않았습니다.


답변

나는 당신이 하나의 진술로 그것을 할 수 있다고 생각하지 않습니다. 더 나은 방법 :

if (!obj.isPresent()) {
    logger.fatal(...);
} else {
    obj.get().setAvailable(true);
}
return obj;


답변

Java 8 Spring은 ifPresentOrElse“옵션과 함께 작동하는 유틸리티 메소드”에서 제공 하여 원하는 것을 달성합니다. 예는 다음과 같습니다.

import static org.springframework.data.util.Optionals.ifPresentOrElse;

ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));


답변

이것을 여러 문장으로 분할해야합니다. 이를 수행하는 한 가지 방법은 다음과 같습니다.

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

obj.ifPresent(o -> o.setAvailable(true));
return obj;

또 다른 방법 (과도하게 설계되었을 수 있음)은 다음을 사용하는 것입니다 map.

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

return obj.map(o -> {o.setAvailable(true); return o;});

만약 obj.setAvailable편리하게 반환 obj, 다음 수 단순히 두 번째 예 :

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

return obj.map(o -> o.setAvailable(true));


답변

우선, dao.find()를 반환 Optional<Obj>하거나 생성해야합니다.

예 :

Optional<Obj> = dao.find();

또는 다음과 같이 스스로 할 수 있습니다.

Optional<Obj> = Optional.ofNullable(dao.find());

이것은 Optional<Obj>존재하거나 Optional.empty()존재하지 않으면 반환 됩니다 .

이제 해결책을 찾아 보겠습니다.

public Obj getObjectFromDB() {
   return Optional.ofNullable(dao.find()).flatMap(ob -> {
            ob.setAvailable(true);
            return Optional.of(ob);
        }).orElseGet(() -> {
            logger.fatal("Object not available");
            return null;
        });
    }

이것은 당신이 찾고있는 하나의 라이너입니다 🙂


답변

이다.orElseRun 방법은 있지만라고합니다 .orElseGet.

의사 코드의 주요 문제 .isPresentOptional<>. 그러나 메서드 .map가있는 Optional<>을 반환합니다 orElseRun.

한 문장에서 정말로 이것을하고 싶다면 이것은 가능하다 :

public Optional<Obj> getObjectFromDB() {
    return dao.find()
        .map( obj -> {
            obj.setAvailable(true);
            return Optional.of(obj);
         })
        .orElseGet( () -> {
            logger.fatal("Object not available");
            return Optional.empty();
    });
}

그러나 이것은 이전에 가졌던 것보다 훨씬 어색합니다.


답변

예를 들어 다음과 같은 몇 가지 “한 줄”솔루션을 만들 수있었습니다.

    obj.map(o -> (Runnable) () -> o.setAvailable(true))
       .orElse(() -> logger.fatal("Object not available"))
       .run();

또는

    obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
       .orElse(o -> logger.fatal("Object not available"))
       .accept(null);

또는

    obj.map(o -> (Supplier<Object>) () -> {
            o.setAvailable(true);
            return null;
    }).orElse(() () -> {
            logger.fatal("Object not available")
            return null;
    }).get();

처럼, 뭔가를 아주 좋은 보이지 않는 orElseRun더 나은 것,하지만 난 당신이 정말 한 줄 솔루션을 원하는 경우의 Runnable에 해당 옵션이 허용 생각합니다.