I have some stream handling code that takes a stream of words and performs some operations on them, then reduces them to a Map
containing the words as keys and the number of occurrences of the word as a Long
value. For the sake of the brevity of the code, I used the jOOL library's Seq
class, which contains a number of useful shortcut methods.
The code compiles just fine if I write it like this:
item.setWordIndex (
getWords (item) // returns a Seq<String>
.map (this::removePunctuation) // String -> String
.map (stemmer::stem) // String -> String
.groupBy(str -> str, Collectors.counting ()));
However, if I attempt to replace the str -> str
lambda with the more self-documenting Function::identity
, I get the following errors:
The method
setWordIndex(Map<String,Long>)
in the typeMyClass
is not applicable for the arguments(Map<Object,Long>)
The typeFunction
does not defineidentity(String)
that is applicable here
Why does Function::identity
behave any differently to str -> str
, which I (perhaps naively) assumed was directly equivalent, and why can't the compiler handle it when it is used?
(And yes, I'm aware I could remove the identity function by moving the previous map
application into the groupBy
operation, but I find the code clearer like this, because it follows the application logic more directly)
You want Function.identity()
(which returns a Function<T, T>
), not Function::identity
(which matches the SAM type Supplier<Function<T, T>>
).
The following code compiles fine:
static String removePunctuation(String x) { return x; }
static String stem(String x) { return x; }
// ...
final Map<String, Long> yeah = Seq.of("a", "b", "c")
.map(Test::removePunctuation)
.map(Test::stem)
.groupBy(Function.identity(), Collectors.counting());