Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 stream agregate generic list to map

I am trying to get myself used with the Java 8 stream functionality by applying it in a small home project. Recently I had the issue reproduced below and despite the fact I understand what the issue is I could not find the fix. I am posting it here hoping to get some explanations and the correct solution.

public class GroupingByStreamTest {
    class Double<A, B> {
        A a;
        B b;

        public Double(A a, B b) {
            this.a = a;
            this.b = b;
        }
    }

    class Triple<A, B, C> extends Double<A, B> {
        C c;

        public Triple(A a, B b, C c) {
            super(a, b);
            this.c = c;
        }
    }

    @Test
    public void shouldGroupToMap() throws Exception {
        List<Triple<String, String, String>> listOfTriples = asList(
            new Triple<>("a-1", "b-1", "c-1"),
            new Triple<>("a-1", "b-2", "c-2"),
            new Triple<>("a-1", "b-3", "c-3"),
            new Triple<>("a-2", "b-4", "c-4"),
            new Triple<>("a-2", "b-5", "c-5"));

        // This code below compiles and executes OK. If I put a   breakpoint
        // in my EDI I can even see the expected Map being created. However
        // if you uncomment the line below and comment the one after it the
        // code will no longer compile. 

        // Map<String, List<Double<String, String>>> myMap =
        Map<Object, List<Double<Object, Object>>> myMap =
        listOfTriples.stream().collect(groupingBy(t -> t.a,
            mapping((Triple t) -> new Double<>(t.b, t.c),toList())));

        assertEquals(2, myMap.size());
    }
}

The compile error I got is

Error:(49, 39) java: incompatible types: inference variable A has incompatible bounds
equality constraints: java.lang.String
lower bounds: java.lang.Object
like image 962
Julian Avatar asked Mar 16 '23 13:03

Julian


2 Answers

You should not use raw types. Either drop the type specification for t at all:

Map<Object, List<Double<Object, Object>>> myMap =
        listOfTriples.stream().collect(groupingBy(t -> t.a,
            mapping(t -> new Double<>(t.b, t.c),toList())));

Or specify its type fully:

Map<Object, List<Double<Object, Object>>> myMap =
        listOfTriples.stream().collect(groupingBy(t -> t.a,
            mapping((Triple<String, String, String> t) -> new Double<>(t.b, t.c),toList())));
like image 173
Tagir Valeev Avatar answered Mar 27 '23 10:03

Tagir Valeev


You have the raw type of Triple in your mapping.

if you adjust your code like this:

Map<String, List<Double<String, String>>> myMap =  
listOfTriples
.stream()
.collect(
  groupingBy(t -> t.a, 
    mapping((Triple<String, String, String> t) -> new Double<>(t.b, t.c), toList())
));

it should work

like image 40
griFlo Avatar answered Mar 27 '23 09:03

griFlo