[java] Java 8의 Optional.ifPresent 및 if-not-present의 기능적 스타일?
Java 8에서는 Optional
객체가 있으면 객체에 무언가를 하고 싶지 않으면 다른 일을 하고 싶습니다 .
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
그러나 이것은 ‘기능적 스타일’이 아닙니다.
Optional
이 ifPresent()
방법을하지만, 나는 체인 드릴 수 없습니다 orElse()
방법.
따라서 나는 쓸 수 없다 :
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
@assylias에 대한 답변으로 Optional.map()
다음과 같은 경우에는 효과 가 없다고 생각 합니다.
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
이 경우 opt
존재하는 경우 속성을 업데이트하고 데이터베이스에 저장합니다. 사용할 수 없으면 새로 작성 obj
하여 데이터베이스에 저장합니다.
두 개의 람다에 주목해야한다 null
.
그러나 opt
존재하는 경우 두 람다가 모두 실행됩니다. obj
업데이트되고 새 개체가 데이터베이스에 저장됩니다. 이것은 return null
첫 번째 람다 때문입니다 . 그리고 orElseGet()
계속 실행될 것입니다.
답변
저에게 @Dane White의 대답은 괜찮습니다. 먼저 Runnable을 사용하는 것을 좋아하지 않았지만 대안을 찾을 수 없었습니다. 여기에서 선호하는 다른 구현
public class OptionalConsumer<T> {
private Optional<T> optional;
private OptionalConsumer(Optional<T> optional) {
this.optional = optional;
}
public static <T> OptionalConsumer<T> of(Optional<T> optional) {
return new OptionalConsumer<>(optional);
}
public OptionalConsumer<T> ifPresent(Consumer<T> c) {
optional.ifPresent(c);
return this;
}
public OptionalConsumer<T> ifNotPresent(Runnable r) {
if (!optional.isPresent()) {
r.run();
}
return this;
}
}
그런 다음 :
Optional<Any> o = Optional.of(...);
OptionalConsumer.of(o).ifPresent(s ->System.out.println("isPresent "+s))
.ifNotPresent(() -> System.out.println("! isPresent"));
업데이트 1 :
가치가 있고 그것을 처리하고 싶을 때 전통적인 개발 방식에 대한 위의 솔루션이지만 기능을 정의하고 실행하려면 다음 개선 사항을 확인하십시오.
public class OptionalConsumer<T> implements Consumer<Optional<T>> {
private final Consumer<T> c;
private final Runnable r;
public OptionalConsumer(Consumer<T> c, Runnable r) {
super();
this.c = c;
this.r = r;
}
public static <T> OptionalConsumer<T> of(Consumer<T> c, Runnable r) {
return new OptionalConsumer(c, r);
}
@Override
public void accept(Optional<T> t) {
if (t.isPresent()) {
c.accept(t.get());
}
else {
r.run();
}
}
그런 다음 다음과 같이 사용할 수 있습니다.
Consumer<Optional<Integer>> c=OptionalConsumer.of(System.out::println, ()->{System.out.println("Not fit");});
IntStream.range(0, 100).boxed().map(i->Optional.of(i).filter(j->j%2==0)).forEach(c);
이 새로운 코드에는 3 가지가 있습니다.
- 기존 객체를 쉽게 사용하기 전에 기능을 정의 할 수 있습니다.
- 각 옵션에 대해 객체 굴절을 생성하지 않음 선택 사항, 하나만, 메모리가 적고 GC가 적습니다.
- 다른 구성 요소와의 더 나은 사용을 위해 소비자를 구현하고 있습니다.
그건 그렇고 지금은 그 이름이 더 묘사 적입니다. 실제로 소비자입니다.>
답변
Java 9 이상을 사용하는 경우 다음 ifPresentOrElse()
방법 을 사용할 수 있습니다 .
opt.ifPresentOrElse(
value -> System.out.println("Found: " + value),
() -> System.out.println("Not found")
);
답변
자바 9 소개
ifPresentOrElse 값이 있으면 값으로 지정된 조치를 수행하고, 그렇지 않으면 주어진 빈 기반 조치를 수행합니다.
Java 8 치트 시트의 탁월한 Optional을 참조하십시오 .
대부분의 사용 사례에 대한 모든 답변을 제공합니다.
아래 요약
ifPresent ()-Optional이 설정되면 무언가를한다
opt.ifPresent(x -> print(x));
opt.ifPresent(this::print);
filter ()-특정 선택적 값을 거부 (필터 아웃)합니다.
opt.filter(x -> x.contains("ab")).ifPresent(this::print);
map ()-존재하는 경우 값을 변환
opt.map(String::trim).filter(t -> t.length() > 1).ifPresent(this::print);
orElse () / orElseGet () – 비어 있음
int len = opt.map(String::length).orElse(-1);
int len = opt.
map(String::length).
orElseGet(() -> slowDefault()); //orElseGet(this::slowDefault)
orElseThrow ()-비어있는 경우 예외적으로 예외 처리
opt.
filter(s -> !s.isEmpty()).
map(s -> s.charAt(0)).
orElseThrow(IllegalArgumentException::new);
답변
대안은 다음과 같습니다.
System.out.println(opt.map(o -> "Found")
.orElse("Not found"));
그래도 가독성이 향상되지는 않는다고 생각합니다.
또는 Marko가 제안한 것처럼 삼항 연산자를 사용하십시오.
System.out.println(opt.isPresent() ? "Found" : "Not found");
답변
또 다른 해결책은 다음과 같이 고차 함수를 사용하는 것입니다.
opt.<Runnable>map(value -> () -> System.out.println("Found " + value))
.orElse(() -> System.out.println("Not Found"))
.run();
답변
즉시 사용할 수있는 좋은 방법은 없습니다. 클리너 구문을 정기적으로 사용하려면 다음과 같은 유틸리티 클래스를 작성할 수 있습니다.
public class OptionalEx {
private boolean isPresent;
private OptionalEx(boolean isPresent) {
this.isPresent = isPresent;
}
public void orElse(Runnable runner) {
if (!isPresent) {
runner.run();
}
}
public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
if (opt.isPresent()) {
consumer.accept(opt.get());
return new OptionalEx(true);
}
return new OptionalEx(false);
}
}
그런 다음 다른 곳에서 정적 가져 오기를 사용하여 다음에 가까운 구문을 얻을 수 있습니다.
import static com.example.OptionalEx.ifPresent;
ifPresent(opt, x -> System.out.println("found " + x))
.orElse(() -> System.out.println("NOT FOUND"));
답변
Java 8 이하 만 사용할 수있는 경우 :
1) spring-data
지금까지 가장 좋은 방법 이 없다면 :
opt.<Runnable>map(param -> () -> System.out.println(param))
.orElse(() -> System.out.println("no-param-specified"))
.run();
이제는 읽기가 어렵고 이해하기가 어렵다는 것을 알고 있지만 개인적으로 나에게 잘 어울리 며이 경우에는 유창한 또 다른 유창한 방법을 보지 못합니다.
2) 당신이 충분히 운 spring-data
이 좋으며 가장 좋은 방법을
사용할 수 있다면 Optionals #ifPresentOrElse입니다 .
Optionals.ifPresentOrElse(opt, System.out::println,
() -> System.out.println("no-param-specified"));
Java 9를 사용할 수 있다면 반드시 다음을 수행해야합니다.
opt.ifPresentOrElse(System.out::println,
() -> System.out.println("no-param-specified"));