2016-05-18 6 views
6

Lassen Sie uns sagen, dass ich eine Liste von ‚A‘ habenIn Java 8 lambdas, wie das ursprüngliche Objekt im Stream zugreifen?

List<A> as; 

Wenn ich ein gutes Stück der Verarbeitung auf jeder A tun wollen, und am Ende der Verarbeitung, möchte ich das Ergebnis nehmen und setzen in einem anderen Bereich von A, was ist der beste Weg, das zu tun?

dh

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

Ich habe den Hinweis auf 'ein' weiter oben in der Lambda-Kette verloren. Gibt es eine Möglichkeit, es zu speichern und darauf zurück zu verweisen?

+1

Wenn das Nachschlagen an 'x' gebunden ist, würde ich eher vorschlagen, den Code zu ändern, um etwas wie 'a.lookup (lookup :: get)' zu erhalten. Dann hättest du ein einfaches forEach. – zeroflagL

+1

'für (A a: as) if (a.getX()! = Null) a.setLookedUpVal (lookup.get (a.getX()));' oder, wenn 'getX()' teuer ist '' (A a: as) {Xx = a.getX(); if (x! = null) a.setLookedUpVal (lookup.get (x)); } '. Vergleichen Sie jede Stream-basierte Lösung mit * dem *, bevor Sie sich entscheiden, sie zu verwenden ... – Holger

Antwort

4

Ich weiß nicht, ob Sie die unveränderten Elemente zugreifen können, aber Sie können Ihre Operationen Kette auf folgende Weise überarbeiten:

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

Jetzt verstehe ich, es macht es komplexer und vielleicht nicht interessant sein, in Lösen Sie Ihr wirkliches Problem.
Es hat jedoch den Vorteil, mit einer Stream<A> zusammen zu arbeiten, die es in manchen Situationen einfacher und erweiterbarer machen könnte als verschiedene Typen in verschiedenen Schritten.

5

Wenn Sie komplexere Szenario haben oder nicht mag aus irgendeinem Grund @Aaron zu beantworten, können Sie die flatMap-Capturing Trick pro jedem äußeren Element einelementige Strom erzeugt tun:

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

Hier haben wir Verschachtelter Stream pro Element, in dem Sie statusfreie Stream-Operationen ausführen können (map, filter, peek und flatMap), die einen Verweis auf das ursprüngliche Element haben. Nachdem das ursprüngliche Element nicht mehr benötigt wird, schließen Sie die flatMap und fahren mit dem ursprünglichen Stream fort. Beispiel:

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

Oder zwei Filter:

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" 

Natürlich ist eine solche einfache Szenarien neu geschrieben werden könnte wie @Aaron vermuten lässt, aber in komplexeren Fällen flatMap-Capturing geeignete Lösung sein kann.

+1

Oder '.flatMap (a -> a.length()> 2 && a.charAt (0) == 'c'? Stream.von (a) : null) 'das ist fast so prägnant wie mit' .filter' ... – Holger