Bu iki yöntem arasındaki fark nedir: Optional.flatMap()
ve Optional.map()
?
Bir örnek takdir edilecektir.
Stream#flatMap
ve ile arasında birebir karşılık vermem Optional#flatMap
.
Bu iki yöntem arasındaki fark nedir: Optional.flatMap()
ve Optional.map()
?
Bir örnek takdir edilecektir.
Stream#flatMap
ve ile arasında birebir karşılık vermem Optional#flatMap
.
Yanıtlar:
Kullanım map
işlevi gerekmez nesne veya dönerse flatMap
işlevini verir eğer bir Optional
. Örneğin:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
Her iki yazdırma ifadesi de aynı şeyi yazdırır.
[flat]Map
Harita işlevini input == null
hiç? Anladığım kadarıyla, Optional
sıralama yoksa, [JavaDoc] ( docs.oracle.com/javase/8/docs/api/java/util/… ) bunu destekliyor gibi görünüyor - " Bir değer varsa, uygulayın .. . "
Optional.of(null)
bir Exception
. Optional.ofNullable(null) == Optional.empty()
.
Her ikisi de isteğe bağlı türden bir şeye bir işlev alır.
map()
isteğe bağlı olarak " olduğu gibi " işlevini uygular :
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
İşleviniz bir işlevse ne olur T -> Optional<U>
?
Sonuç şimdi bir Optional<Optional<U>>
!
İşte bununla flatMap()
ilgili: eğer fonksiyonunuz zaten bir döndürürse Optional
, flatMap()
biraz daha zekidir ve onu çift sarmaz, geri döner Optional<U>
.
İki işlevsel deyimin bileşimidir: map
ve flatten
.
Not: - aşağıda harita ve fistingp işlevinin gösterimi verilmiştir, aksi takdirde İsteğe bağlı olarak yalnızca bir dönüş türü olarak kullanılmak üzere tasarlanmıştır.
Bildiğiniz gibi İsteğe bağlı, tek bir nesne içerebilen veya içermeyen bir tür kapsayıcıdır, bu nedenle boş bir değer beklediğiniz her yerde kullanılabilir (İsteğe bağlı olarak düzgün kullanılırsa hiçbir zaman NPE'yi göremezsiniz). Örneğin, boş olabilecek bir kişi nesnesini bekleyen bir yönteminiz varsa, yöntemi şöyle bir şey yazmak isteyebilirsiniz:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
Burada otomatik olarak İsteğe bağlı bir türe sarılmış bir String türü döndürdünüz.
Kişi sınıfı buna benziyorsa, yani telefon da isteğe bağlıdır
class Person{
private Optional<String> phone;
//setter,getter
}
Bu durumda, harita işlevini çağırmak döndürülen değeri İsteğe bağlı olarak sarar ve şöyle bir şey verir:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS; NullPointerExceptions olmadan yaşayamazsanız, hiçbir zaman isteğe bağlı olarak isPresent () ile kontrol etmeden get yöntemini (gerekirse) çağırmayın.
Person
uzaklaşacak gibi görünüyor çünkü sınıfınız yanlış kullanıyor Optional
. API'nin Optional
bu gibi üyelerde kullanılması niyeti karşı - bkz. Mail.openjdk.java.net/pipermail/jdk8-dev/2013-Eylül/…
Bana yardımcı olan iki fonksiyonun kaynak koduna bir göz atmaktı.
Harita - sonucu İsteğe bağlı olarak sarar.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flatMap - 'raw' nesnesini döndürür
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
flatMap
"Ham" nesneyi döndürür "ile ne demek istiyorsun ? flatMap
ayrıca eşlenen nesneyi bir Optional
. Fark durumunda olmasıdır flatMap
eşleştirici fonksiyonu eşlenen nesne kaydırılır Optional
ise map
kendi içinde bir nesne sarar Optional
.
Optional.map()
:Her öğeyi alır ve değer varsa işleve aktarılır:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Şimdi eklenen üç değerden birine sahiptir: true
veya varsa false
bir İsteğe bağlıoptionalValue
veya boş bir İsteğe bağlı içine sarılmış .
Kullanabileceğiniz sonucu işlemeniz ifPresent()
gerekmiyorsa, dönüş değeri yoktur:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:Aynı akış yöntemine benzer şekilde çalışır. Akarsu akışını düzleştirir. Fark, eğer değer sunuluyorsa fonksiyona uygulanır. Aksi takdirde, boş bir isteğe bağlı döndürülür.
İsteğe bağlı değer işlevleri çağrıları oluşturmak için kullanabilirsiniz.
Yöntemlerimiz olduğunu varsayalım:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
Sonra tersin karekökünü hesaplayabilirsiniz, örneğin:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
veya isterseniz:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
Ya olursa inverse()
veya squareRoot()
döner Optional.empty()
, sonuç boş.
Optional<Double>
dönüş türü olarak tipe sahiptir.
Tamam. Sen iç içe geçmiş Opsiyoneller karşı karşıya olduğunuzda sadece kullanım 'flatMap' gerek . İşte örnek.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
Akış gibi, İsteğe bağlı # harita İsteğe bağlı tarafından sarılmış bir değer döndürür. Bu yüzden iç içe bir isteğe bağlı oluruz Optional<Optional<Insurance>
. Ve ② olarak, bunu bir Sigorta örneği olarak eşlemek istiyoruz, bu trajedi böyle oldu. Kök yuvalanmış Optionals. Kabuklardan bağımsız olarak temel değeri alabilirsek, halledeceğiz. FlatMap bunu yapar.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
Sonunda, Java8 Sistematik olarak çalışmak istiyorsanız, Java 8 In Action'ı size şiddetle tavsiye ettim.