Ben kullanıcı tarafından önerilmiş düzenleme dayalı bu ikinci cevabı ekliyorum srborlongan için benim diğer cevap . Önerilen tekniğin ilginç olduğunu düşünüyorum, ancak cevabımda bir düzenleme olarak gerçekten uygun değildi. Diğerleri de kabul etti ve önerilen düzenleme oylandı. (Ben seçmenlerden biri değildim.) Yine de tekniğin değeri var. Srborlongan'ın kendi cevabını göndermesi iyi olurdu. Bu henüz gerçekleşmedi ve StackOverflow'un düzenleme geçmişinin sislerinde kaybolmasını istemedim, bu yüzden bunu ayrı bir cevap olarak ortaya çıkarmaya karar verdim.
Temel olarak teknik, Optional
üçlü bir işleç ( ? :
) veya bir if / else deyimini kullanmaktan kaçınmak için yöntemlerin bazılarını akıllıca kullanmaktır .
Satır içi örneğim şu şekilde yeniden yazılabilir:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
Bir yardımcı yöntem kullanan bir örneğim şu şekilde yeniden yazılabilir:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
return opt.map(Stream::of)
.orElseGet(Stream::empty);
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
YORUM
Orijinal ve değiştirilmiş sürümleri doğrudan karşılaştıralım:
// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
Orijinal, eğer işçi benzeri bir yaklaşımsa basittir: bir Optional<Other>
; bir değeri varsa, bu değeri içeren bir akış döndürürüz ve değeri yoksa boş bir akış döndürürüz. Oldukça basit ve açıklanması kolay.
Modifikasyon zekidir ve şartlardan kaçınma avantajına sahiptir. (Bazı kişilerin üçlü operatörden hoşlanmadığını biliyorum. Yanlış kullanılırsa kodun anlaşılmasını zorlaştırabilir.) Ancak, bazen işler çok akıllı olabilir. Değiştirilen kod ayrıca bir ile başlar Optional<Other>
. Sonra Optional.map
aşağıdaki gibi tanımlanan çağırır :
Bir değer varsa, sağlanan eşleme işlevini ona uygulayın ve sonuç boş değilse, sonucu açıklayan bir İsteğe Bağlı döndürün. Aksi takdirde boş bir İsteğe bağlı döndürün.
map(Stream::of)
Çağrısı döndürür Optional<Stream<Other>>
. İsteğe bağlı girişinde bir değer varsa, döndürülen İsteğe Bağlı tek bir Diğer sonucu içeren bir Akış içerir. Ancak değer yoksa, sonuç boş bir İsteğe bağlı olur.
Ardından, çağrı orElseGet(Stream::empty)
türünde bir değer döndürür Stream<Other>
. Girdi değeri varsa, tek eleman olan değeri alır Stream<Other>
. Aksi takdirde (giriş değeri yoksa) boş döner Stream<Other>
. Böylece sonuç doğrudur, orijinal koşullu kodla aynıdır.
Cevabımın tartışıldığı yorumlarda, reddedilen düzenleme ile ilgili olarak, bu tekniği "daha özlü ama aynı zamanda daha belirsiz" olarak tanımlamıştım. Ben bunun yanındayım. Ne yaptığını anlamak biraz zaman aldı ve ayrıca ne yaptığının yukarıdaki açıklamasını yazmak da biraz zamanımı aldı. Anahtar incelik gelen dönüşümü Optional<Other>
için Optional<Stream<Other>>
. Bunu yaptıktan sonra bu mantıklı, ama benim için açık değildi.
Bununla birlikte, başlangıçta belirsiz olan şeylerin zamanla deyimsel hale gelebileceğini kabul edeceğim. Bu teknik, en azından eklenene kadar Optional.stream
(eğer varsa) pratikte en iyi yol olabilir.
GÜNCELLEME: Optional.stream
JDK 9'a eklendi.
.flatMap(Optional::toStream)
, versiyonunuzla gerçekten neler olduğunu görüyorsunuz.