In der folgenden Klasse übergebe ich die Methodenreferenz WordCounterEx::accumulate
als zweiten Parameter an die Methode reduce. Die Signatur der Reduce-Methode lautet:Methodenverweis erfüllt nicht den funktionalen Schnittstellenvertrag, sondern kompiliert. Wie ist das möglich?
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
Der zweite Parameter der Reduce-Methode muss daher das BiFunction-Rezept erfüllen. Aber die übergebene Akkumulationsmethode ist keine BiFunction (sie hat nur einen Parameter). Warum es noch kompilieren?
public class WordCounterEx {
private final int counter;
private final boolean lastSpace;
public WordCounterEx(int counter, boolean lastSpace) {
this.counter = counter;
this.lastSpace = lastSpace;
}
public int countWords(Stream<Character> stream) {
WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true),
//HOW CAN THIS WORK? here must come BiFunction - R apply(T t, U u);
WordCounterEx::accumulate,
WordCounterEx::combine);
return wordCounter.counter;
}
public WordCounterEx accumulate(Character c) {
if(Character.isWhitespace(c)) {
return lastSpace ?
this :
new WordCounterEx(counter, true);
} else {
return lastSpace ?
new WordCounterEx(counter+1, false) :
this;
}
}
public WordCounterEx combine(WordCounterEx wordCounter) {
return new WordCounterEx(counter + wordCounter.counter
,wordCounter.lastSpace /*does not matter*/);
}
}
Beachten Sie, dass in Java 8 könnten Sie this' als Argument übergeben 'haben muss, was perfekt mit der Signatur übereinstimmt: 'public WordCounterEx accumulate (WordCounterEx this, Character c)'. Dies entspricht der Version ohne "this" als Argument, wie in der Frage. –