Reputation: 33
I'm using Spring Boot under Java 8 and I'm trying to perform a type cast inside a lambda expression, but can't get it to work after a lot of research and try/error.
Suppose I have a list like this:
List<Foo> list;
that is filled in a step of a batch process, and because of datasource restrictions, the class Foo needs to be declared like this (with all its members as String):
class Foo {
private String id;
private String quantity;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getQuantity {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
}
Once the list is loaded, I need to do some grouping and summing based on id, given that the quantity String represents a decimal number.
The following code gives me an error because summingDouble is expecting a Double, not a String:
Map<String, Double> grouping = list.stream().collect(Collectors.groupingBy(Foo::getId, Collectors.summingDouble(Foo::getQuantity)));
I managed it to fix the error by adding an extra function to Foo class, like this:
public Double getQuantityAsDouble() {
return StringUtils.isEmpty(quantity) ? new Double(0) : Double.valueOf(quantity);
}
and doing the call this way:
Map<String, Double> grouping = list.stream().collect(Collectors.groupingBy(Foo::getId, Collectors.summingDouble(Foo::getQuantityAsDouble)));
but it seems a poor solution to me.
Is there any way to direct cast Foo::getQuantity from String to Double inside Collectors.summingDouble() without the need to add bloat functions to the original bean?
Thanks!
Upvotes: 3
Views: 2333
Reputation: 4087
Java doesn't do implicit conversion from String to Double, which is what your code is implying.
You need an explicit conversion, which can be accomplished with with a conversion in the stream:
Map<String, Double> grouping = list.stream().collect(Collectors.groupingBy(Foo::getId,
Collectors.summingDouble(foo -> Double.parseDouble(foo.getQuantity()))));
(or use Double.valueOf if those semantics are more appropriate)
EDITED: clarity
EDITED MORE: to add explanation based on comment.
The double colon syntax (e.g. Foo::getQuantity
) creates a method reference. Double.valueOf only knows how to deal with a string. In this case, java needs some "imperative help" to connect the dots, hence the imperative lambda, rather than the function reference.
Upvotes: 3