代码之家  ›  专栏  ›  技术社区  ›  Saravana Kumar M

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

  •  2
  • Saravana Kumar M  · 技术社区  · 6 年前

    要点:我们正在尽可能使用java 8流和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));
    

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

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

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

    提前感谢!

    2 回复  |  直到 6 年前
        1
  •  5
  •   Jacob G.    6 年前

    您没有指定如何(或是否)存储年龄,因此我现在只将其作为打印语句。尽管如此,只需在 Map 并打印每个 List (映射 Person 对象的年龄):

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

    如果您想将其存储在另一个 地图 ,然后您可以很容易地将其收集到一个:

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

    笔记 : -1 如果不存在平均值,则返回,这假定中存在getter方法 调用 getAge ,返回 int

        2
  •  3
  •   Stefan Zhelyazkov    6 年前

    您可以这样做:

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