Reputation: 41127
Let's say I have this code:
Map<String, String> map;
// later on
map.entrySet().stream().map(MyObject::new).collect(Collectors.toList());
And I have a MyObject
Constructor
which takes two arguments of type String
.
I want to be able to do this but I cannot.
I know I can do e -> new MyObject(e.getKey(), e.getValue())
but prefer MyObject::new
.
Similar code works for Set<String>
and List<String>
with one argument constructor of MyObject
class.
Upvotes: 6
Views: 22559
Reputation: 61
class MyObject {
private final String k;
private final String v;
MyObject(String s1, String s2) {
k = s1;
v = s2;
}
MyObject(Map.Entry<String, String> e) {
this(e.getKey(), e.getValue());
}
public String toString() {
return "key: " + k + ' ' + "value: " + v;
}
}
You will be able to call
List<MyObject> myObjectList = map.entrySet().stream().map(MyObject::new).collect(Collectors.toList());
Upvotes: 2
Reputation: 49656
The problem with the constructor is that it defines two parameters, while Function#apply
demanded by Stream#map
accepts only one.
You could write a static factory method for MyObject
class MyObject {
public static MyObject of(Map.Entry<String, String> e) {
return new MyObject(e.getKey(), e.getValue());
}
}
and refer to it like
map(MyObject::of)
Before you do so, ask yourself if one pretty-looking line in a plain processing chain somewhere is worthy of a new constructor or utility method.
Upvotes: 2
Reputation: 124844
map.entrySet().stream().map(MyObject::new).collect(Collectors.toList()));
And I have a
MyObject
Constructor which takes two arguments of typeString
. I want to be able to do this but I cannot.
In map.entrySet().stream().map(...)
, Java is expecting a Function
,
mapping one value to another value.
One value.
From the stream, the function receives a value of type Map.Entry<String, String>
,
but your constructor takes two String
arguments.
Java doesn't automagically expand a Map.Entry<String, String>
to a pair of String
s to pass to your constructor.
You have to do that unwrapping manually.
Upvotes: 3
Reputation: 56499
use a lambda:
map.entrySet()
.stream()
.map(e -> new MyObject(e.getKey(), e.getValue()))
.collect(Collectors.toList());
otherwise the only way to use a method reference is by creating a function as such:
private static MyObject apply(Map.Entry<String, String> e) {
return new MyObject(e.getKey(), e.getValue());
}
then do something like:
map.entrySet()
.stream()
.map(Main::apply)
.collect(Collectors.toList());
Where Main
is the class containing the apply
method.
Upvotes: 11