I found that function interface and getMethod seem to be replaceable, What makes it work?
public class App {
public static void main(String[] args) {
Map<String, String> collect = Stream.of(new App(), new App(), new App())
.collect(Collectors.toMap(App::getString, (app) -> "aaa"));
}
public String getString() {
return "str";
}
}
But when I use lambda to replace getMethod, it fails . Why this does not work
Map<String, String> collect = Stream.of(new App(), new App(), new App())
.collect(Collectors.toMap(() -> "str", (app) -> "aaa"));
Collectors.toMap
requires a Function<? super T, ? extends K>
as its first parameter, where T
is the type of elements in the stream, and K
is the key type of the map you want.
In this case, you have a stream of App
s and you want a Map<String, String>
, so T
is App
and K
is String
. In other words, you need a function that accepts an App
, and returns a String
.
App::getString
is such a Function<? super T, ? extends K>
. You might be wondering why it accepts a App
when getString
accepts no parameters. Notice how getString
is an instance method, and you are referring to it without an instance! A method reference of the form ClassName::instanceMethodName
implicitly accepts an extra parameter of type ClassName
, because you need an instance of that class to call it!
On the other hand, your lambda is not such a function. It accepts no parameters, as indicated by the empty brackets at the start (()
). Your lambda expression would be represented by the Supplier<String>
functional interface, not the Function<App, String>
that you need.
To use a lambda expression here, simply do what you did to the second parameter of toMap
, and add a lambda parameter:
.collect(Collectors.toMap((app) -> "str", (app) -> "aaa"));
// ^^^
Note that this is required even if you don't use app
in the lambda expression.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments