2014-11-11 7 views
9

Ich kämpfe mit der Definition und Verwendung desVerwendung von Funktionstyp kongruent Lambda-Ausdrücke in Java 8

Stream.collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) 

method in Java 8.

Die Methodensignatur enthält BiConsumer typisierte Parameter. Das BiConsumer FunctionalInterface definiert eine funktionale Methode accept(Object, Object). Soweit ich verstehe, kann ich nun jeden Lambda-Ausdruck verwenden, der congruent zu dieser funktionalen Schnittstelle ist.

Aber das Beispiel, das in dem Stream.collect JavaDoc erwähnt wird, ist z.B.

List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); 

Ich verstehe nicht, warum ArrayList.add(E e) (Einzelparameter) ist deckungsgleich mit den BiConsumer.accept(T t, U u) Methode (zwei Parametern) und kann als Akkumulator-Funktion im Sammelverfahren verwendet werden.

Wie Sie sehen, habe ich offensichtlich einen Mangel an Verständnis und schätzen jede Erklärung.

+2

es ist eine Abkürzung für '(Liste, Element) -> Liste .add (Element) '. Es gibt ein Duplikat, aber ich kann es jetzt nicht finden ... – assylias

+0

http://StackOverflow.com/a/23025159/2711488 hat eine verständliche Illustration. [Diese Frage] (http://stackoverflow.com/q/23139725/2711488) könnte auch verwandt sein. – Holger

Antwort

12

Der Akkumulator BiConsumer der beiden Parameter sind (1) die Liste selbst und (2) das Element, um es hinzuzufügen. Dies:

List<String> asList = stringStream.collect(
    ArrayList::new, 
    ArrayList::add, 
    ArrayList::addAll 
); 

entspricht dies:

List<String> asList = stringStream.collect(
    () -> new ArrayList<>(), 
    (list, item) -> list.add(item), 
    (list1, list2) -> list1.addAll(list2) 
); 

, die das gleiche Ergebnis wie diese geben wird:

List<String> asList = stringStream.collect(
    new Supplier<ArrayList<String>>() { 
     @Override 
     public ArrayList<String> get() { 
      return new ArrayList<>(); 
     } 
    }, 

    new BiConsumer<ArrayList<String>,String>() { 
     @Override 
     public void accept(ArrayList<String> list, String item) { 
      list.add(item); 
     } 
    }, 

    new BiConsumer<ArrayList<String>,ArrayList<String>>() { 
     @Override 
     public void accept(ArrayList<String> list1, ArrayList<String> list2) { 
      list1.addAll(list2); 
     } 
    } 
); 
+0

+1 Danke - einfacher als ich dachte ;-) – FrVaBe

+0

So richtig wie @Misha s Antwort aber ein bisschen mehr Detail - also akzeptiert – FrVaBe

9

ArrayList::add hat eigentlich 2 Parameter. Das Objekt ArrayList, auf dem Sie die Methode add und den Parameter add aufrufen.

ArrayList::add entspricht (list, element) -> list.add(element) und so funktioniert es als BiConsumer

+0

+1 Danke - einfacher als ich dachte ;-) – FrVaBe