给出需要排序和分组的对象列表:
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,而且我猜它是一个有序集合,因为它来自有序地图类型,所以这是我当前的解决方案:< / p>
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来实现所需的输出。那么,我该怎么做呢?
答案 0 :(得分:2)
如评论中所述,指的是question that is very similar(实际上,我几乎认为它是重复的……),groupBy
调用具有不同的风格,其中之一允许传入要创建的地图的工厂。
因此,无需显式包装“ groupBy
”调用的结果,即可创建新的TreeMap
,因为您可以直接创建TreeMap
。该地图(及其values()
集合!)将通过键进行排序。映射的值是列表,这些列表是使用下游收集器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);
}
}
}
答案 1 :(得分:0)
根据说明进行修改,以更正先前的帖子。其他答案之间的唯一区别是将values()结果馈送到ArrayList构造函数中以创建列表列表。
// Create some data
Random r = new Random(29);
String codes = "ABCD";
List<Widget> widgetList = r.ints(10, 0, 4).mapToObj(
n -> new Widget(codes.substring(n, n + 1), "N" + i++)).collect(
Collectors.toList());
// Now create the list of lists.
List<List<Widget>> listofWidgets = new ArrayList<>(
widgetList.stream().collect(Collectors.groupingBy(Widget::getCode,
TreeMap::new,
Collectors.toList())).values());
// Display them
for (List<?> list : listofWidgets) {
System.out.println(list);
}
小部件类
class Widget {
String widgetCode;
String widgetName;
public Widget(String wc, String wn) {
widgetCode = wc;
widgetName = wn;
}
public String getCode() {
return widgetCode;
}
public String getName() {
return widgetName;
}
public String toString() {
return "{" + widgetCode + ":" + widgetName + "}";
}
}