如何使用java 8流和lambdas迭代和处理其值为元素列表的映射的值

时间:2018-04-27 04:23:23

标签: java java-8 functional-programming

要点:我们试图尽可能用java 8流和lambdas重写旧的Java代码。

问题: 我有一个地图,其键是一个字符串,值是用户定义的对象列表。

Map<String, List<Person>> personMap = new HashMap<String, List<Person>>();
personMap.put("A", Arrays.asList(person1, person2, person3, person4));
personMap.put("B", Arrays.asList(person5, person6, person7, person8));

这里的人根据姓名的起始字符进行分组。

我想在地图中找到每个关键字列表中人员的平均年龄。

同样,我已经尝试过stackoverflow中提到的很多东西,但没有一个与我的案例匹配,或者很少在语法上不起作用。

提前致谢!

2 个答案:

答案 0 :(得分:5)

你没有说明你希望如何(或者如果)想要存储年龄,所以我现在只将它作为一个打印声明。然而,它就像迭代Map中的每个条目并打印每个List的平均值(在将Person对象映射到它们的年龄之后)一样简单:

personMap.forEach((k, v) -> {
    System.out.println("Average age for " + k + ": " + v.stream().mapToInt(Person::getAge).average().orElse(-1));
});

如果您想将其存储在另一个Map中,那么您可以非常轻松地将其收集到一个:

personMap.entrySet()
         .stream()
         .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                                                            .stream()
                                                            .mapToInt(Person::getAge)
                                                            .average()
                                                            .orElse(-1)));

注意:如果不存在平均值,则返回-1,这假设Person中存在一个名为getAge的getter方法,返回{{1} }}

答案 1 :(得分:3)

你可以这样做:

// this will get the average over a list
Function<List<Person>, Double> avgFun = (personList) ->
   personList.stream()
      .mapToInt(Person::getAge)
      .average()
      .orElseGet(null);

// this will get the averages over your map
Map<String, Double> result = personMap.entrySet().stream()
   .collect(Collectors.toMap(
      Map.Entry::getKey,
      entry -> avgFun.apply(entry.getValue())
   ));