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

Java 8:如何将一个列表串成一个列表的列表?

史景铄
2023-03-14

给定需要排序和分组的对象列表:

static class Widget {
    // ...
    public String getCode() { return widgetCode; }
    public String getName() { return widgetName; }
}

List<Widget> widgetList = Arrays.asList(
    // several widgets with codes and names
);

我想将列表分组为列表中的列表,按widgetCode分组,每个子列表的元素按照它们在原始列表中遇到的顺序排列。我知道可以使用groupingby收集器将它们分组到列表映射中:

Map<String,List<Widget>> widgetMap = widgetList.stream()
    .collect(groupingBy(Widget::getCode));

我并不认为键是理所当然地排序的,所以我采取了额外的步骤,将整个内容加载到SortedMap类型中:

SortedMap<String,List<Widget>> sortedWidgetMap = new TreeMap<String,List<Widget>>(
    widgetList.stream()
        .collect(groupingBy(Widget::getCode))
);

我知道我可以通过使用.values()从sortedWidgetMap获取集合,而且我猜它是一个有序集合,因为它来自一个有序的map类型,所以这就是我当前的解决方案

Collection<List<Widget>> widgetListList = new TreeMap<String,List<Widget>>(
    widgetList.stream()
        .collect(groupingBy(Widget::getCode))
).values();
widgetListList.forEach(System.out::println);  // do something with the data

到目前为止,这是可行的,但我不相信最终得到的widgetListList是否真的保证是正确的顺序(即widgetCode)或者子列表是否会按照它们在原始列表中找到的顺序构建。而且,我认为必须有可能单独使用流API来实现我想要的输出。那么,我怎样才能把这件事做得更好呢?

共有1个答案

拓拔骁
2023-03-14

正如在一个评论中提到的,在提到一个非常相似的问题时(事实上,我几乎认为它是一个重复的问题……),groupby调用有不同的风格,其中之一允许传入要创建的映射的工厂。

因此,不需要在创建新的树状图时显式包装“简单”GroupBy调用的结果,因为您可以直接创建树状图。此映射(及其值()集合!)将按钥匙排序。映射的值是列表,它们是使用下游收集器toList()创建的,该收集器显式地表示它将按照遇到的顺序收集结果。

所以以下确实应该是一个简单、正确、高效的解决方案:

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class CollectToListOfList {
    static class Widget {
        String code;
        String name;

        Widget(String code, String name) {
            this.code = code;
            this.name = name;
        }

        public String getCode() {
            return code;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return code + ": " + name;
        }

    }

    public static void main(String[] args) {
        List<Widget> widgetList = Arrays.asList(
            new Widget("0", "A"), 
            new Widget("1", "B"), 
            new Widget("2", "C"),
            new Widget("3", "D"), 
            new Widget("0", "E"), 
            new Widget("1", "F"), 
            new Widget("2", "G"),
            new Widget("3", "H"), 
            new Widget("0", "I"), 
            new Widget("1", "J"));

        Collection<List<Widget>> result = widgetList.stream()
            .collect(Collectors.groupingBy(Widget::getCode, TreeMap::new, Collectors.toList()))
            .values();

        for (List<Widget> list : result) {
            System.out.println(list);
        }

    }
}
 类似资料:
  • 问题内容: 我有 我想要 问题答案:

  • 问题内容: 如何将所有列表(在“ val”列中)组合成唯一列表(集合),例如? 我可以使用以下代码解决此问题。我想知道是否有一种更简单的方法可以从列中获取所有唯一值而又不迭代数据帧行? 问题答案: 导出到嵌套然后应用于拼合列表的另一种解决方案: 时间 : 如果类型不是,则使用和:

  • 当我试图将从表t_comment_photo查询的userPhoto映射到java类ToyComment中的列表元素时,我得到了错误。 我试图修复的resultMap是: 我尝试了和,但都不起作用。 怎么把它修好?

  • 问题内容: [‘a’,’a’,’b’,’c’,’c’,’c’] 至 和 问题答案: x=[‘a’,’a’,’b’,’c’,’c’,’c’] >>> map(x.count,x) [2, 2, 1, 3, 3, 3] >>> dict(zip(x,map(x.count,x))) {‘a’: 2, ‘c’: 3, ‘b’: 1} >>>

  • 在这里,我有两个项目列表,我想要合并到一个列表中,并在保存到数据库之前删除重复项。但是我得到一个错误,“非静态方法不能从静态上下文引用”。虽然我知道该消息的含义,但我不知道如何在Java8流的上下文中解决它。拜托,救命。 下面是错误消息的快照

  • 问题内容: 在Java中将列表拆分为两个子列表的最简单,最标准和/或最有效的方法是什么?可以更改原始列表,因此无需复制。方法签名可以是 [EDIT] 返回原始列表上的视图,如果修改了原始视图,该视图将无效。因此,除非它也放弃了原始参考文献,否则无法使用(或者,如Marc Novakowski的回答所述,使用但立即复制结果)。 问题答案: 快速半伪代码: 它使用标准的List实现方法,并避免了所有循