2016-05-18 16 views
6

Powiedzmy mam listę „A”W java 8 lambdach, jak uzyskać dostęp do oryginalnego obiektu w strumieniu?

List<A> as; 

Jeśli chcę zrobić sporo części przetwarzania na każdy, a na koniec przetwarzania, chcę wziąć wynik i umieścić go w innej dziedzinie A, jaki jest najlepszy sposób na zrobienie tego?

tj

as.stream(). 
map(a -> a.getX()). 
filter(x -> x != null). 
map(x -> lookup.get(x)). 

At this point how to say y -> a.setLookedUpVal(y)? 

Straciłem odniesienie do 'a' dalej w górę łańcucha lambda. Czy istnieje sposób na zapisanie go i odesłanie do niego lub coś takiego?

+1

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

+1

'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

Odpowiedz

4

Nie wiem, czy można uzyskać dostęp do niemodyfikowanych elementów, ale można przerobić swój łańcuch operacji w następujący sposób:

as.stream() 
    .filter(a -> a.getX() != null) 
    .forEach(a -> a.setLookedUpVal(lookup.get(a.getX())) 

Teraz rozumiem, to sprawia, że ​​bardziej skomplikowane i nie może być interesująca rozwiązywanie twojego prawdziwego problemu.
Ma jednak tę zaletę, że działa razem z Stream<A>, co w niektórych sytuacjach może uczynić go prostszym i bardziej rozszerzalnym niż różne typy na różnych etapach.

5

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.

+1

Lub '.flatMap (a -> a.length()> 2 && a.charAt (0) == 'c'? Stream.of (a) : null) ', który jest prawie tak zwięzły jak użycie' .filter' ... – Holger