Java8:如何将一个列表流化为一个列表列表?

Java8:如何将一个列表流化为一个列表列表?,java,java-8,java-stream,Java,Java 8,Java Stream,给定需要排序和分组的对象列表: static class Widget { // ... public String getCode() { return widgetCode; } public String getName() { return widgetName; } } List<Widget> widgetList = Arrays.asList( // several widgets with codes and names ); 我

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

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

List<Widget> widgetList = Arrays.asList(
    // several widgets with codes and names
);
我并不想当然地认为密钥是经过排序的,因此我采取了额外的步骤,将整个内容加载到SortedMap类型中:

SortedMap<String,List<Widget>> sortedWidgetMap = new TreeMap<String,List<Widget>>(
    widgetList.stream()
        .collect(groupingBy(Widget::getCode))
);
SortedMap sortedWidgetMap=新树映射(
widgetList.stream()
.collect(分组方式(小部件::getCode))
);
我知道我可以使用.values()从sortedWidgetMap获取集合,我猜这是一个有序集合,因为它来自有序映射类型,所以这是我当前的解决方案:

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
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);
        }

    }
}
集合widgetListList=新树映射(
widgetList.stream()
.collect(分组方式(小部件::getCode))
).values();
widgetListList.forEach(System.out::println);//对数据做点什么

到目前为止,这是可行的,但我不确定生成的widgetListList是否真的保证顺序正确(即通过widgetCode),或者子列表是否会按照在原始列表中找到的顺序构建。此外,我认为必须能够单独使用流API来实现我想要的输出。那么,我怎样才能做得更好呢?

根据澄清修改了之前的文章。其他答案之间的唯一区别是values()结果被输入ArrayList构造函数以创建列表列表

//创建一些数据
随机r=新随机(29);
字符串代码=“ABCD”;
List-widgetList=r.ints(10,0,4).mapToObj(
n->新建小部件(代码。子字符串(n,n+1),“n”+i++)。收集(
收藏家;
//现在创建列表列表。
List listofWidgets=新建ArrayList(
widgetList.stream().collect(收集器.groupingBy(小部件::getCode、,
树映射::新的,
Collectors.toList()).values());
//展示它们
for(列表:listofWidgets){
系统输出打印项次(列表);
}
小部件类


类小部件{
字符串widgetCode;
字符串widgetName;
公共小部件(字符串wc、字符串wn){
widgetCode=wc;
widgetName=wn;
}
公共字符串getCode(){
返回widgetCode;
}
公共字符串getName(){
返回widgetName;
}
公共字符串toString(){
返回“{”+widgetCode+”:“+widgetName+”}”;
}
}

正如一条评论中提到的,指的是一个(事实上,我几乎认为它是一个重复的…),
groupBy
调用有不同的风格,其中一个允许传递要创建的映射的工厂

因此,不需要显式地将“simple”
groupBy
调用的结果包装到新的
TreeMap
的创建中,因为您可以直接创建
TreeMap
。此映射(及其
values()
collection!)将按键排序。映射的值是列表,它是使用下游收集器
toList()
创建的,该收集器明确表示将按遭遇顺序收集结果

因此,以下确实应该是一个简单、正确和有效的解决方案:

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
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);
        }

    }
}
导入java.util.array;
导入java.util.Collection;
导入java.util.List;
导入java.util.TreeMap;
导入java.util.stream.collector;
公共类集合列表{
静态类小部件{
字符串代码;
字符串名;
小部件(字符串代码、字符串名称){
this.code=代码;
this.name=名称;
}
公共字符串getCode(){
返回码;
}
公共字符串getName(){
返回名称;
}
@凌驾
公共字符串toString(){
返回代码+“:”+名称;
}
}
公共静态void main(字符串[]args){
List widgetList=Arrays.asList(
新小部件(“0”、“A”),
新部件(“1”、“B”),
新部件(“2”、“C”),
新部件(“3”、“D”),
新小部件(“0”、“E”),
新部件(“1”、“F”),
新部件(“2”,“G”),
新部件(“3”、“H”),
新小部件(“0”、“I”),
新部件(“1”、“J”);
收集结果=widgetList.stream()
.collect(Collectors.groupingBy(Widget::getCode,TreeMap::new,Collectors.toList())
.values();
对于(列表:结果){
系统输出打印项次(列表);
}
}
}

对于排序,您可以给
TreeMap
一个
Comparator
进行排序。从
SortedMap.values()
的javadoc:“集合的迭代器以相应键的升序返回值。”,因此不必担心解决方案的顺序(效率可能会提高),您可以提供一个排序映射到
groupingBy
,例如,如下所示:不,这不是我的目标。我想要的是一个列表。列表中的第一个元素是包含所有s的列表,其中包含widgetCode“a”,第二个元素是包含所有s的列表,其中包含widgetCode“B”,依此类推。也许我的玩具问题太傻了,说不清楚!你的问题很好。显然我是唯一一个不明白的人。谢谢你的澄清。