이미하고있는 것처럼 더 간결하게 할 수는 없습니다.
당신은 당신이 원하지 않는 것을 주장 .filter(Optional::isPresent)
하고 .map(Optional::get)
.
그러나 이것은 결과적으로 당신이 지금에 매핑 설명 메소드 @StuartMarks에 의해 해결 된 Optional<T>
그래서 지금 당신이 사용해야 .flatMap(this::streamopt)
하고, get()
결국.
따라서 여전히 두 개의 문으로 구성되며 이제 새로운 방법으로 예외를 얻을 수 있습니다! 모든 옵션이 비어 있으면 어떻게됩니까? 그런 다음 findFirst()
빈 옵션을 반환하고 get()
실패합니다!
그래서 당신이 가진 것 :
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
입니다 당신이 원하는 것을 달성하는 가장 좋은 방법은 실제로, 그것은 당신이 같은 결과를 저장할 것입니다 T
아닌 같은 Optional<T>
.
나는 CustomOptional<T>
포장하고 Optional<T>
추가 방법을 제공하는 클래스를 만들 자유를 얻었습니다 flatStream()
. 다음을 확장 할 수 없습니다 Optional<T>
.
class CustomOptional<T> {
private final Optional<T> optional;
private CustomOptional() {
this.optional = Optional.empty();
}
private CustomOptional(final T value) {
this.optional = Optional.of(value);
}
private CustomOptional(final Optional<T> optional) {
this.optional = optional;
}
public Optional<T> getOptional() {
return optional;
}
public static <T> CustomOptional<T> empty() {
return new CustomOptional<>();
}
public static <T> CustomOptional<T> of(final T value) {
return new CustomOptional<>(value);
}
public static <T> CustomOptional<T> ofNullable(final T value) {
return (value == null) ? empty() : of(value);
}
public T get() {
return optional.get();
}
public boolean isPresent() {
return optional.isPresent();
}
public void ifPresent(final Consumer<? super T> consumer) {
optional.ifPresent(consumer);
}
public CustomOptional<T> filter(final Predicate<? super T> predicate) {
return new CustomOptional<>(optional.filter(predicate));
}
public <U> CustomOptional<U> map(final Function<? super T, ? extends U> mapper) {
return new CustomOptional<>(optional.map(mapper));
}
public <U> CustomOptional<U> flatMap(final Function<? super T, ? extends CustomOptional<U>> mapper) {
return new CustomOptional<>(optional.flatMap(mapper.andThen(cu -> cu.getOptional())));
}
public T orElse(final T other) {
return optional.orElse(other);
}
public T orElseGet(final Supplier<? extends T> other) {
return optional.orElseGet(other);
}
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSuppier) throws X {
return optional.orElseThrow(exceptionSuppier);
}
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
@Override
public boolean equals(final Object obj) {
return optional.equals(obj);
}
@Override
public int hashCode() {
return optional.hashCode();
}
@Override
public String toString() {
return optional.toString();
}
}
다음 flatStream()
과 같이 내가 추가 한 것을 볼 수 있습니다.
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
로 사용 :
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.flatMap(CustomOptional::flatStream)
.findFirst()
.get();
당신은 여전히 를 반환해야합니다 Stream<T>
당신은 반환 할 수 없으므로, 여기에 T
있기 때문에 경우, !optional.isPresent()
다음, T == null
당신이 같은 선언하지만, 다음 경우 .flatMap(CustomOptional::flatStream)
추가하려고 할 null
스트림에 해당이 불가능합니다.
예를 들어 :
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
로 사용 :
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.map(CustomOptional::getTOrNull)
.findFirst()
.get();
이제 NullPointerException
스트림 작업 내부를 던질 것 입니다.
결론
사용한 방법이 실제로 가장 좋은 방법입니다.
.flatMap(Optional::toStream)
는 것을 알았습니다.