2016-05-18 26 views
6

en Her A işleme adil düşeni yapmak istiyorsanız ben 'A'Java 8 lambda'da, akıştaki orijinal nesneye nasıl erişilir?

List<A> as; 

bir listesi var ve işleme sonunda, ben sonuç almak ve koymak istediğimizi varsayalım A'nın başka bir alanında, bunu yapmanın en iyi yolu nedir?

yani

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)? 

lambda zinciri içinde 'a' ayrıca referans kaybetmiş. Onu saklamanın ve ona geri dönmenin bir yolu var mı?

+1

Arama, x'e bağlıysa, kodunuzu değiştirmeyi önerebilirim; örneğin, bir .lookup (lookup :: get) 'gibi bir şey elde etmek için. O zaman basit bir 'forEach' olurdu. – zeroflagL

+1

'(a a: as) için (a.getX()! = Null) a.setLookedUpVal (lookup.get (a.getX()));' veya getX() 'pahalıysa,' için (A a: as) {X x = a.getX(); eğer (x! = boş) a.setLookedUpVal (lookup.get (x)); } '. Kullanmaya karar vermeden önce her Stream tabanlı çözümü * bu * ile karşılaştırın * – Holger

cevap

4

değiştirilmeden elemanlar erişebilir eğer bilmiyorum, ancak aşağıdaki şekilde operasyonlar zinciri yeniden işleme olabilir: Şimdi bunun daha karmaşık hale getirir ve ilginç olmayabilir anlıyorum

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

gerçek dünya probleminizi çözüyor.
Bununla birlikte, Stream<A> ile birlikte çalışmanın avantajı, bazı durumlarda farklı adımlarda farklı tiplerden daha basit ve daha genişletilebilir hale getirebilir.

5

daha karmaşık senaryo var ya nedense cevap @Aaron beğenmezseniz, her dış öğe başına tek eleman akışı oluşturarak flatMap-yakalama hile yapabilirsiniz: Elimizdeki İşte

as.stream(). 
    flatMap(a -> Stream.of(a.getX()). 
     filter(x -> x != null). 
     map(x -> a)). 
    forEach(System.out::println); 

Orijinal öğeye başvuruda bulunarak, herhangi bir durum bilgisi olmayan akış işlemlerini (map, filter,ve flatMap) yapabileceğiniz her öğe için iç içe akış. Orijinal eleman gereksiz hale geldikten sonra, flatMap'u kapatır ve orijinal akışa devam edersiniz. Örnek:

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". 

Ya da iki filtreler:

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" 
@Aaron anlaşılacağı gibi böyle basit senaryolar yeniden yazılabilir Tabii

ancak daha karmaşık durumlarda flatMap-yakalama uygun çözüm olabilir.

+1

Veya '.flatMap (a -> a.length()> 2 && a.charAt (0) == 'c'? Stream.of (a) : null) '.filter' kullanarak neredeyse özlü… – Holger