Jeśli masz bardziej skomplikowany scenariusz lub nie lubią @Aaron odpowiedzieć z jakiegoś powodu, można rade flatMap przechwytywania tworzenie jednego elementu strumienia za każdym elemencie zewnętrznym:
as.stream().
flatMap(a -> Stream.of(a.getX()).
filter(x -> x != null).
map(x -> a)).
forEach(System.out::println);
Tutaj mamy zagnieżdżony strumień elementów, w którym można wykonać dowolne operacje strumienia bezstanowego (map
, filter
, peek
i flatMap
) mające odniesienie do oryginalnego elementu. Po tym, jak oryginalny element stanie się zbędny, zamykasz flatMap
i kontynuujesz z oryginalnym strumieniem. Przykład:
Stream.of("a", "bb", "ccc", "dd", "eeee")
.flatMap(a -> Stream.of(a.length())
.filter(x -> x > 2)
.map(x -> a))
.forEach(System.out::println);
// prints "ccc" and "eeee".
lub dwóch filtrów:
Stream.of("a", "bb", "ccc", "dd", "eeee")
.flatMap(a -> Stream.of(a.length())
.filter(x -> x > 2)
.map(x -> a.charAt(0)) // forget the length, now check the first symbol
.filter(ch -> ch == 'c')
.map(x -> a)) // forget the first symbol, reverting to the whole string
.forEach(System.out::println);
// prints only "ccc"
Oczywiście takie proste scenariusze mogą być zapisane jak @Aaron wskazuje, lecz w mniej skomplikowanych przypadkach flatMap wychwytujące może być korzystne rozwiązanie.
Jeśli odnośnik jest powiązany z 'x', wolę zasugerować zmianę kodu, aby uzyskać coś w stylu' a.lookup (lookup :: get) '. Wtedy miałbyś proste 'forEach'. – zeroflagL
'dla (A a: as) if (a.getX()! = Null) a.setLookedUpVal (lookup.get (a.getX()));' lub, jeśli 'getX()' jest kosztowne, 'dla (A a: as) {X x = a.getX(); if (x! = null) a.setLookedUpVal (lookup.get (x)); } '. Porównaj każde rozwiązanie oparte na strumieniu z * tym * przed podjęciem decyzji o jego użyciu ... – Holger