java - 使用 Java 8 流将数据分组到映射中

标签 java java-8 java-stream

我想使用 Java 8 流 API 对数据进行分组。所有具有parent_id 的行都应该分组在一起。以下是示例文本文件。结果应该是一个映射,其中 id 将是整数,值将是相应的分组行。例如,在下面的情况下,结果将是包含 3 个条目的 map 。键 1 有 2 个值,键 2 无值,键 3 有 1 个值。

id      name    parent_id
1       A       (null)
2       B       1
3       C       1
4       D       (null)
5       E       (null)
6       F       5

代码片段是:

Map<String, List<FileVO>> map= list.stream()
        .collect(groupingBy(FileVO::getParentId, toList()));

输出可以类似于:{A,{B,C}}, {D,{}},{E,{F}}

简单的规则是:当parentId不为空时,这些记录应该被分组到一个列表中。这个列表将被视为 map 中的值。它的键是parentId,它是实际的id(列id的值,它不会为空。而parentId可以为空。如果一条记录的parentId为空,并且没有其他记录在其parentId列中具有其Id,那么它将被视为具有键但为空值的单个对象。)

最佳答案

我认为你不能在单流中做到这一点。

Map<Integer, String> roots = list.stream()
            .filter(myObject -> myObject.getParentId() == null)
            .collect(Collectors.toMap(MyObject::getId, MyObject::getName));

输出通过其 id 和名称都是父级

{1=A, 4=D, 5=E}

Map<Integer, List<String>> groupByParentId = list.stream()
            .filter(myObject -> myObject.getParentId() != null)
            .collect(Collectors.groupingBy(MyObject::getParentId,
                    Collectors.mapping(MyObject::getName, toList())));

输出按parentId分组

{1=[B, C], 5=[F]}

最后一步是:

roots.forEach((k,v)->map.put(v,groupByParentId.getOrDefault(k,new ArrayList<>())));

流版本更新:复杂度为 O(n^2)

  list.stream()
            .filter(myObject -> myObject.getParentId() == null)
            .collect(Collectors.toMap(MyObject::getName, MyObject::getId))
            .forEach((k, v) -> map.put(k, list.stream()
            .filter(myObject -> myObject.getParentId() == v)
            .map(MyObject::getName)
            .collect(Collectors.toList())));

或者你也可以使用像这样的非流方式:(个人更喜欢非流版本)

注意:这样根就是Map<String,Integer> roots

String root = "";
for (MyObject myObject : list) {
    if (myObject.getParentId() == null) {
       root = myObject.getName();
       map.put(root, new ArrayList<>());
    }
    if (roots.get(root).equals(myObject.getParentId())){
      map.computeIfAbsent(root, k -> new ArrayList<>()).add(myObject.getName());
    }
}

关于java - 使用 Java 8 流将数据分组到映射中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57101998/

相关文章:

Java流从集合中获取单个元素

java - ArrayList 根据另一个 arrayList 的值在列表的每个映射中放置一个字段

java - 无法在两行中创建两个 TextView

java - Nebula Grid 的多行工具提示

Java泛型捕获内部类

Java:使用 lambda 向文件添加行号的优雅方式

java - 任务“:workflows-java:NodeDriver. main()”执行失败

java - native 操作系统外观 Netbeans 不能与 UIManager.setLookAndFeel(nativeLF) 一起使用;

java - 如何将 Java 代码迁移到更新的 jdk(例如 1.8)

java-8 - Java 8 使用流和过滤器将 Map 的值检索到数组中