Given a list of objects that need to be sorted and grouped:
static class Widget {
// ...
public String getCode() { return widgetCode; }
public String getName() { return widgetName; }
}
List<Widget> widgetList = Arrays.asList(
// several widgets with codes and names
);
I want to group the list into a list-of-lists, grouped by widgetCode, with the elements of each sub-list in the order they were encountered in the original list. I know that I can group them into a Map of lists using the groupingBy Collector:
Map<String,List<Widget>> widgetMap = widgetList.stream()
.collect(groupingBy(Widget::getCode));
I do not take for granted that the keys are sorted, so I've taken the extra step of loading the whole thing into a SortedMap type:
SortedMap<String,List<Widget>> sortedWidgetMap = new TreeMap<String,List<Widget>>(
widgetList.stream()
.collect(groupingBy(Widget::getCode))
);
I know I can get a Collection from sortedWidgetMap by using .values(), and I guess it is an ordered collection because it comes from an ordered map type, so that's my current solution:
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
This works so far, but I'm not confident that the resulting widgetListList is actually guaranteed to be in the right order (i.e. by widgetCode) or that the sub-lists will be built in the order they were found in the original list. Also, I think it must be possible to use the Stream API alone to achieve the output I want. So, how can I do this better?