Java 8流将通用列表聚合成映射

4

我正在通过将Java 8 流功能应用于一个小型家庭项目中来逐渐熟悉它。最近,我遇到了以下问题,尽管我理解这个问题,但是我找不到解决方法。我在这里发布帖子,希望得到一些解释和正确的解决方案。

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());
    }
}

我遇到的编译错误是:
Error:(49, 39) java: incompatible types: inference variable A has incompatible bounds
equality constraints: java.lang.String
lower bounds: java.lang.Object

Map<String, List<Double<String, String>>> myMap = // Map<Object, List<Double<Object, Object>>> myMap = listOfTriples.stream() .collect( Collectors.groupingBy(t -> t.a, Collectors.mapping((Triple<String, String, String> t) -> new Double<>(t.b, t.c), Collectors.toList()))); - griFlo
你在lambda表达式中的mapping收集器中使用了原始类型Triple参数。尝试使用Triple<String, String, String>,或者更简单地使用mapping(t -> new Double<>(...)),编译器会自动推断出它是一个Triple<String, String, String>。(顺便说一下,在groupingBy(t -> t.a)中没有指定它。) - Alexis C.
2
不应该将类命名为Double,因为它会与java.lang.Double发生冲突,这会导致未来的问题。可以将其命名为Pair或类似的名称。而在另一个代码中,Triple extends Double也是一种坏味道。三元组不是二元组,一旦尝试为其添加正确的equalshashCode方法,就会注意到问题。 - Holger
2个回答

4

您不应该使用原始类型。可以完全省略对t的类型规定:

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

或者完整指定它的类型:

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())));

3

你的映射中有 Triple 的原始类型。

如果你按照以下方式调整你的代码:

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())
));

它应该可以正常工作


那个结果出来得又快又准确。我也曾经尝试过这个,但可能是在其他地方出了问题,错误地得出这不是正确的方法。非常感谢你。 - Julian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接