当前位置: 首页 > 知识库问答 >
问题:

Java 8 映射到使用流和收集器的集合的子列表条目

梁明辉
2023-03-14

我有一个<code>Person<code>对象的集合:。

public class Person {

  String name;

  ChildrenListHolder childrenListHolder;
}

public class ChildrenListHolder {
   List<Children> children;
}

public class Children {
   String childrensName;
}

(实体结构由第三方提供。

现在,我需要一张地图

例如(简体):

Person father: {name: "John", childrensListHolder -> {"Lisa", "Jimmy"}}
Person mother: {name: "Clara", childrensListHolder -> {"Lisa", "Paul"}}
Person george: {name: "George", childrensListHold -> "Paul"}}

地图,我需要的是

Map<String, List<Person>> map: {"Lisa"  -> {father, mother},
                                "Jimmy" -> {father},
                                "Paul"  -> {mother, george}}

我可以用一堆for和if来做到这一点。但是我如何使用流和收集器来做到这一点。我尝试了很多方法,但是我不能得到预期的结果。TIA。


共有2个答案

花玄裳
2023-03-14

我可以用一堆for's和if's来做到这一点。

我知道您要求流/收集器解决方案,但在任何情况下,使用Map#computeIfAbsend嵌套for循环也可以正常工作:

Map<String, List<Person>> map = new HashMap<>();
for(Person p : persons) {
    for(Children c : p.childrenListHolder.children) {
        map.computeIfAbsent(c.childrensName, k -> new ArrayList<>()).add(p);
    }
}

这是使用在集合上引入的新的foreach方法编写的:

Map<String, List<Person>> map = new HashMap<>();
persons.forEach(p -> p.childrenListHolder.children.forEach(c -> map.computeIfAbsent(c.childrensName, k -> new ArrayList<>()).add(p)));

当然,它不像Tunaki的解决方案(1)那样是一行程序,也不容易并行化,但是您也不需要“一堆”if来实现这一点(并且您还避免了创建临时map entries实例)。

太叔马鲁
2023-03-14

给定一个列表

Map<String,List<Person>> map =
    persons.stream()
           .flatMap(p -> p.childrenListHolder.children.stream().map(c -> new AbstractMap.SimpleEntry<>(c, p)))
           .collect(Collectors.groupingBy(
             e -> e.getKey().childrensName,
             Collectors.mapping(Map.Entry::getValue, Collectors.toList())
           ));

这是在人员上创建一个Stream。然后每个人都由包含孩子和每个孩子的人的元组平面映射。最后,我们按孩子的名字分组并将所有人收集到一个列表中。

假设有适当的构造函数的示例代码:

public static void main(String[] args) {
    List<Person> persons = Arrays.asList(
        new Person("John", new ChildrenListHolder(Arrays.asList(new Children("Lisa"), new Children("Jimmy")))),
        new Person("Clara", new ChildrenListHolder(Arrays.asList(new Children("Lisa"), new Children("Paul")))),
        new Person("George", new ChildrenListHolder(Arrays.asList(new Children("Paul"))))
    );

    Map<String,List<Person>> map =
        persons.stream()
               .flatMap(p -> p.childrenListHolder.children.stream().map(c -> new AbstractMap.SimpleEntry<>(c, p)))
               .collect(Collectors.groupingBy(
                 e -> e.getKey().childrensName,
                 Collectors.mapping(Map.Entry::getValue, Collectors.toList())
               ));

    System.out.println(map);
}

 类似资料:
  • 我有这个代码: 它产生的是 很高兴我应该如何写映射方法来得到一个地图,它会给我:

  • 我有一个对象的集合,每个对象都有一个元素的集合,例如: 如何使用Java 8函数式编程来过滤和收集类型等于“a”的集合? 我尝试了以下方法: 但我得到以下错误: 变量'filteredChildren'初始值设定项'parents。stream()。forEach(p- 如何按类型筛选嵌套集合并收集它们?

  • 假设你有一张这样的物体地图(尽管想象它更大): rtype=133,有两个! 我想对Streams做的是这样的: 我在理解Collectors&groupBy的工作原理时遇到了一些麻烦,但我想这可能会用于本例。 在Java streams API中进行编码的正确方法是什么? 我很难找到类似的地图例子(人们在他们的例子中更多地使用列表)

  • 假设我有以下工作的lambda表达式: 我想在过滤器语句之前创建一个具有2个值的流。所以我想做一个映射,但仍然保留原始值。我想实现这样的事情: 这可能与Java8流?我已经看了收集(GroupingBy()),但仍然没有成功。

  • 2020-07-08->{0->{hourquarter.first->5.5,ehourquarter.second->10.2,...},1->{ehourquarter.first->33.2,ehourquarter.second->30.1,...},...} 它是一个整数图(小时:从0到23)的局部日期图,二倍的每小时四分之一图。 我需要得到一个包含每个日期累加的map >,这意味着如

  • 问题内容: 在上面的代码中,我可以期望中的名称顺序始终与中的顺序相同吗? 问题答案: 是的,只要您没有将并行流显式转换为模式,即使您正在使用并行流,也可以期望这样做。 顺序永远不会在顺序模式下更改,但可能会在并行模式下更改。流变得无序: 如果您通过调用将其明确转换为无序模式 如果流源报告它是无序的(例如,流是无序的,因为顺序取决于实现,因此您不能依赖它) 如果您使用的是无序终端操作(例如,进行操作