使用Java 8动态创建具有组合键的映射

时间:2017-03-29 19:28:10

标签: java-8

我想创建一个如下的地图 - >

Map<Pair<MyClass.a, MyClass.b>, MyClass>>.

我有一个对象列表 - &gt;

List<MyClass>

这里的Pair是一个类,已经在我的项目中,所以我想使用它。

我需要帮助才能从Java 8流创建它。

我确实尝试过::

ls.stream().collect(Collectors.toMap(new Pair(MyClass.a, MyClass.b), MyClass));

但是我收到了一个错误。我是Java 8的新手并且正在努力学习它。

添加示例:

class Person {
   String name ;
   int age ;
   // Some other variables
}

我有List<Person>的列表。

在我的要求中,我需要一个键= {name,age},使用对类。

class Pair<T,U> {     
    Pair(T t, U u) {
        this.t = t
        this.u = u
    }

    // Overridden hashCode && equals methods
}

现在我要创建一个像Map<Pair<String, Int>, Person>

这样的地图

我收到一个编译错误,上面写着“不是功能界面”。

我确信必须通过java 8流和收集方式。

1 个答案:

答案 0 :(得分:6)

要创建函数,必须使用 lambda表达式。编写像new Pair(MyClass.a, MyClass.b)这样的表达式是不够的,而是指定一个具有参数的函数,该函数将是Person实例,即p -> new Pair<>(p.name, p.age)。或者,您可以将参数设为显式:(Person p) -> new Pair<>(p.name, p.age)

对于Map创建操作,您必须决定,您想要什么。如,

Map<Pair<String, Integer>, List<Person>> map
    = list.stream().collect(Collectors.groupingBy(p -> new Pair<>(p.name, p.age)));

会将每个密钥映射到具有该名称/年龄组合的所有Person个实例的列表。

相比之下

Map<Pair<String, Integer>, Person> map
    = list.stream().collect(Collectors.toMap(p -> new Pair<>(p.name, p.age), p -> p));

会将名称/年龄对映射到单个Person实例,但如果有多个具有相同的键,则抛出异常。您可以指定一个函数来解决此类冲突,例如

Map<Pair<String, Integer>, Person> map = list.stream().collect(
    Collectors.toMap(p -> new Pair<>(p.name, p.age), p -> p, (first, next) -> first));

将保留第一个,而

Map<Pair<String, Integer>, Person> map = list.stream().collect(
    Collectors.toMap(p -> new Pair<>(p.name, p.age), p -> p, (prev, last) -> last));

将覆盖上一个匹配项,最后是每个名称/年龄组合的最后一个Person实例。