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

如何使用Java8流和lambda迭代和处理其值为元素列表的映射的值,java,java-8,functional-programming,Java,Java 8,Functional Programming,要点:我们正在尽可能用Java8流和lambda重写我们的旧java代码 问题: 我有一个映射,它的键是字符串,值是用户定义对象的列表 Map<String, List<Person>> personMap = new HashMap<String, List<Person>>(); personMap.put("A", Arrays.asList(person1, person2, person3, person4)); personMap.pu

要点:我们正在尽可能用Java8流和lambda重写我们的旧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));
Map personMap=newhashmap();
personMap.put(“A”,array.asList(person1,person2,person3,person4));
personMap.put(“B”,数组.asList(person5,person6,person7,person8));
在这里,根据姓名的起始字符对人员进行分组

我想找出地图上每一个关键点列表上的人的平均年龄

同样,我也尝试了stackoverflow中提到的许多事情,但没有一件与我的情况相匹配,或者有几件在语法上不起作用

提前谢谢

您没有指定如何(或是否)存储年龄,因此我现在将其作为打印语句。尽管如此,只需在
映射
中迭代每个条目,并打印每个
列表
的平均值即可(将
对象映射到其年龄后):

如果您想将其存储在另一张
地图中
,则可以非常轻松地将其收集到一张地图中:

personMap.entrySet()
         .stream()
         .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                                                            .stream()
                                                            .mapToInt(Person::getAge)
                                                            .average()
                                                            .orElse(-1)));
注意
-1
在不存在平均值的情况下返回,这假设
Person
中存在一个名为
getAge
的getter方法,返回一个
int
您可以这样做:

// 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())
   ));
//这将获得列表的平均值
函数avgFun=(个人列表)->
personList.stream()
.mapToInt(Person::getAge)
.average()
.orElseGet(空);
//这将得到地图上的平均值
映射结果=personMap.entrySet().stream()
.collect(collector.toMap)(
Map.Entry::getKey,
entry->avgFun.apply(entry.getValue())
));

您能分享您尝试过的任何代码吗?personMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,“我被困在这里…”);我只是想分享一下。这有点奇怪,在eclipse中,当我键入下面的元素时。它以某种方式将元素视为类型对象,而不提供对象类型以外的方法。personMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,element->element.getValue().stream().mapToInt(Person::getAge).average().orElse(-1));我认为这是可行的,但在流中使用流是明智的吗?这很好,但显然有一些流开销会使它比传统的for循环效率更低。除非内部列表很大,否则你也无法从并行流中获益;如果你还需要什么,请告诉我!你知道下面的内容吗?为什么会这样?在eclipse中,当我键入下面的“element”时,它以某种方式将元素视为类型对象,而不提供对象类型以外的方法建议。personMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,element->element.getValue().stream().mapToInt(Person::getAge).average().orElse(-1));我在Intellij工作得很好。您是否同时使用最新版本的Eclipse和Java?谢谢@Stefan。这也很优雅。
// 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())
   ));