Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not infer functional interface type in groupBy Java 8

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()));
    }
}
like image 788
secret129 Avatar asked Jan 09 '18 16:01

secret129


People also ask

Which functional interface is currently introduced in Java 8?

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.

What is the use of functional interface in Java 8 when to use functional interface in Java 8?

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.

Why do I need a functional interface to work with lambdas?

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.


1 Answers

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.

like image 107
Sweeper Avatar answered Sep 20 '22 21:09

Sweeper