2016-10-03 1 views
3

Ich möchte Methodenverweise im Collect (Collectors.toMap (..)) -Aufruf eines Streams verfassen. Im folgenden Beispiel habe ich Code, der ohne eine Methode Referenz meine Aufgabe erfüllt:Java 8-Methodenreferenzen im Stream-Collector verfassen

class A { 
    private String property1; 
    private B property2; 

    public String getProperty1() { return property1; } 
    public B getProperty2() { return property2; } 
} 

class B { 
    private String property3; 

    public String getProperty3() { return property3; } 
} 

public class Main { 
    public static void Main() { 
     List<A> listOfA = /* get list */; 

     Map<String, String> = listOfA.stream() 
      .collect(toMap(x -> x.getProperty1(), x -> x.getProperty2().getProperty3())); 
    } 
} 

Es ist trivial x -> x.getProperty1()-A::getProperty1() zu ändern. Es ist jedoch nicht so trivial mit x -> x.getProperty2().getProperty3(). Ich würde eine der folgenden arbeiten:

.collect(toMap(A::getProperty1, ((Function)A::getProperty2).andThen((Function)B::getProperty3))) 

oder

.collect(toMap(A::getProperty1, ((Function)B::getProperty3).compose((Function)A::getProperty2))) 

Aber sie beide geben mir den Fehler Non-static method cannot be referenced from static context.

+3

Es isn Das wird kein besserer Weg sein. Das Original Lambda ist das Beste, was du bekommen wirst. –

+4

Jede Antwort, die Sie am Ende haben, wird länger, klobiger und unantastbarer sein als der Lambda-Ausdruck. Warum willst du einen anderen Weg gehen? – Tunaki

+0

Ich erkunde das meistens aus Neugierde, zumindest in dieser speziellen Formulierung der Frage. Selbst die zwei Beispiele, die ich zur Verfügung gestellt habe (die nicht funktionieren), sind umständlicher und weniger lesbar als das Lambda. Allerdings ist die Zusammensetzung der Methode eine mächtige Funktion, die ich öfter verwenden würde, wenn ich könnte. Wenn einer von Ihnen erklären könnte, warum dies nicht erlaubt ist, und zusätzlich, in welchen Fällen ich die Methodenzusammensetzung verwenden kann (zum Beispiel, wenn alle Methoden statisch wären, wäre das möglich?), Wäre das extrem nützlich und akzeptabel Antwort meiner Meinung nach. Vielen Dank! –

Antwort

3

A::getProperty2 ist ein Function<A, B> (das ist eine Funktion, die eine Instanz von A übernimmt und eine Instanz von B zurückgibt).

können Sie werfen und komponieren sie als:

((Function<A, B>)A::getProperty2).andThen(B::getProperty3) 

Oder Sie können eine Funktion Hersteller wie erstellen:

public static <A, B, R> Function<A, R> compose(
     Function<A, B> f1, Function<B, R> f2) { 
    return f1.andThen(f2); 
} 

Und es verwenden, um zu komponieren wie:

compose(A::getProperty2, B::getProperty3) 
+1

'A :: getProperty2' ist eine gültige Methodenreferenz für eine' Funktion', sie kann nicht als 'Lieferant' verwendet werden, da sie einen Parameter vom Typ' A' benötigt. –

+0

@DidierL, du hast Recht. Meine Antwort wurde aktualisiert. – ericbn

+0

Also mein Fehler war, es auf "Funktion" anstatt auf "Funktion " zu werfen, wie Sie geklärt haben. Vielen Dank! –

Verwandte Themen