2015-04-28 7 views
11

Ich bin neu zu Lambda-Ausdrücke und versuche, sie zu verwenden, um den folgenden Code auf das Lambda-Äquivalent zu reduzieren. Ich habe reduce und flatMap und forEach sowie einige andere Dinge untersucht, aber mir fehlt offensichtlich etwas, weil alles, was ich versuche, entweder syntaktisch falsch ist oder ich keine Referenz für das habe, was ich brauche.Java-Lambda-Ausdruck für verschachtelte Schleifen mit bedingten

Ich muss eine Analyse jedes Elements für alle anderen Elemente in einer Sammlung durchführen. Ich habe das als verschachtelte Schleifen mit einer Bedingung codiert. Sobald nicht übereinstimmende Elemente identifiziert wurden, wird eine Berechnung unter Verwendung beider Elemente durchgeführt. Schließlich möchte ich eine Sammlung von Ergebnissen für jede Vergleichsberechnung.

So, hier ist der ursprüngliche Code:

final List<Element> updated = new ArrayList<>(elements.size()); 

for (final Element first : elements) { 
    Attribute newAttribute = first.getAttribute(); 

    for (final Element second : elements) { 
     if (!first.equals(second)) { 
      newAttribute = newAttribute.add(computeChange(first, second)); 
     } 
    } 
    final Element newElement = new Element(first.getEntry(), newAttribute, first.getValue()); 
    updated.add(newElement); 
} 

Dann habe ich viele Variationen von Lambda-Ausdrücke versucht, von denen die einfachste ist:

elements.parallelStream() 
     .map(first -> new Element(first.getEntry(), first.getAttribute().add(
     computeChange(first, second)), first 
     .getValue())).collect(Collectors.toList())); 

Offensichtlich ist dies falsch, da keine ist Verweis auf Sekunde verfügbar für mich und keine Bedingung/Filter für die Sekunde, die nicht gleich der ersten ist.

Wie reduziere ich diese verschachtelte Schleife mit der bedingten Rückgabe einer Auflistung an einen Lambda-Ausdruck?

Jede Hilfe hier wird sehr geschätzt.

+3

Das ist hart, weil Ihr 'newAttribute = newAttribute.add (...)' Updates sind nicht parallelizable. Dies wäre einfacher, wenn Sie alle "computeChange" -Ergebnisse aggregieren und dann ein "Attribut" (oder "Element") aus diesem Aggregat erstellen könnten. –

+0

Ich würde es einfach so lassen wie es ist. –

+0

Was gibt 'computeChange' zurück? Ein 'Element',' Attribut' oder eine Zahl? –

Antwort

3

Versuchen:

elements.stream() 
    .map(first -> { 
     Attribute newAttribute = elements.stream().filter(second -> !first.equals(second)) 
       .map(second -> computeChange(first, second)) 
       .reduce(first.getAttribute(), (a, b) -> a.add(b)) 
       return new Element(first.getEntry(), newAttribute, first.getValue()); 
      }).collect(Collectors.toList())); 
+4

Ich glaube nicht, dass '.foreach (newAttribute :: add);' funktionieren wird, da 'add' scheinbar ein neues Attribut erzeugt. Vielleicht funktioniert 'reduce' allerdings. –

+0

@tobias_k Die Foreach meldet den Fehler: Die Methode foreach (Attribut :: add) ist für den Typ Stream nicht definiert. Durch die Verwendung von reduce wird der Fehler behoben. – Todd

+0

pgerstoft, @tobias_k Ich musste das Argument der foreach/reduce auf Attribute ändern: addieren Sie sonst ich erhielt den Fehler "Der Typ Attribut definiert nicht hinzufügen (Attribut, Attribut), die hier anwendbar ist". Ich gebe jedoch keine Komponententests ab, daher glaube ich nicht, dass das wiederholte Update/Add ordnungsgemäß funktioniert. Ich werde immer weiter nach dir suchen, aber wenn du irgendwelche Vorschläge hast, würde ich sie gerne hören. – Todd

Verwandte Themen