java - Java 8:如何将列表流式传输到列表列表中?
问题描述
给定需要排序和分组的对象列表:
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中获取一个集合,我猜它是一个有序集合,因为它来自一个有序的地图类型,所以这是我目前的解决方案:
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),或者子列表将按照它们在原始列表中的顺序构建。另外,我认为必须可以单独使用 Stream API 来实现我想要的输出。那么,我怎样才能更好地做到这一点呢?
解决方案
正如评论中提到的,提到一个非常相似的问题(事实上,我几乎认为它是重复的......),groupBy
调用有不同的风格,其中一个允许传入工厂的地图那是要被创造的。
因此,无需将“简单”groupBy
调用的结果显式包装到 new 的创建中TreeMap
,因为您可以TreeMap
直接创建。此地图(及其values()
集合!)将按密钥排序。map 的值是列表,它们是使用下游收集器创建的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);
}
}
}
推荐阅读
- wordpress - WooCommerce 购物车中一种语言的 Polylang 翻译问题
- jquery - 此路由不支持方法 POST
- firebase - 如何在 Firebase 上调用“可调用函数”时设置授权标头
- node.js - 如何在节点 js 中处理 JSON 字符串数组
- excel - 如何制作比较图表以在每个工作表上显示来自两个工作簿的数据
- c++ - UE4:将纹理设置为材质 (C++)
- java - 为什么 WorkManager 在夏莫设备上不起作用?
- laravel - 在laravel中生成网页的pdf
- docker - 如何正确使用具有预计卷和 configMaps 的子目录
- python - 在请求中发现 Scrapy 和无效 cookie