คุณไม่สามารถทำให้รัดกุมมากขึ้นในขณะที่คุณกำลังทำอยู่
คุณอ้างว่าคุณไม่ต้องการและ.filter(Optional::isPresent)
.map(Optional::get)
สิ่งนี้ได้รับการแก้ไขแล้วโดยวิธีการที่ @StartMarks อธิบายอย่างไรก็ตามในขณะนี้คุณได้แมปไปที่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)
ด้วยรุ่นของคุณคุณจะเห็นสิ่งที่เกิดขึ้นจริง