I am not sure this has been answered earlier or not. Can anyone please tell me what is the problem with third groupBy
which I've written ? Why it can not infer ?
class TestGroupBy
{
enum LifeCycle {
ANNUAL, PERENNIAL
}
private String name;
private LifeCycle lifeCycle;
TestGroupBy(String name, LifeCycle lifeCycle) {
this.name = name;
this.lifeCycle = lifeCycle;
}
LifeCycle getLifeCycle() {
return this.lifeCycle;
}
static EnumMap mySupplier() {
return new EnumMap(TestGroupBy.class);
}
public static void main(String[] args) {
List<TestGroupBy> garden = new ArrayList<>();
garden.add(new TestGroupBy("Test1", TestGroupBy.LifeCycle.ANNUAL));
garden.add(new TestGroupBy("Test2", TestGroupBy.LifeCycle.PERENNIAL));
garden.add(new TestGroupBy("Test4", TestGroupBy.LifeCycle.ANNUAL));
garden.add(new TestGroupBy("Test5", TestGroupBy.LifeCycle.PERENNIAL));
// This works
garden.stream()
.collect(Collectors.groupingBy(e -> e.getLifeCycle()));
// This works
garden.stream()
.collect(Collectors.groupingBy(
e -> e.getLifeCycle(),
TestGroupBy::mySupplier,
Collectors.toSet()
));
// This does not work
garden.stream()
.collect(Collectors.groupingBy(
e -> e.getLifeCycle(), // Can not resolve method getLifeCycle()
new EnumMap(TestGroupBy.class),
Collectors.toSet()));
}
}
From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. A functional interface can have any number of default methods.
Java 8 provides some built-in functional interfaces and if we want to define any functional interface then we can make use of the @FunctionalInterface annotation. It will allow us to declare only a single method in the interface.
Surely lambda expression can be one-time used as your commented code does, but when it comes to passing lambda expression as parameter to mimic function callback, functional interface is a must because in that case the variable data type is the functional interface.
Stop using raw types!
This is mySupplier
without raw types:
static EnumMap<LifeCycle, Set<TestGroupBy>> mySupplier() {
return new EnumMap<>(LifeCycle.class);
}
The key type of an EnumMap
must be an enum type, so you should use LifeCycle
as the first argument. The second argument is what the collector you use at the end returns. You used toSet
here, so I suppose you want a set of TestGroupBy
.
That's how your supplier should look like, with proper generic arguments and LifeCycle.class
as the key type of EnumMap
!
Now, you can do this:
garden.stream()
.collect(Collectors.groupingBy(
e -> e.getLifeCycle(),
() -> new EnumMap<>(LifeCycle.class),
Collectors.toSet()));
Note that your have to add () ->
to make it a supplier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With