Java 8 is not maintaining the order while grouping
Not maintaining the order is a property of the Map
that stores the result. If you need a specific Map
behavior, you need to request a particular Map
implementation. E.g. LinkedHashMap
maintains the insertion order:
groupedResult = people.collect(Collectors.groupingBy(
p -> new GroupingKey(p, groupByColumns),
LinkedHashMap::new,
Collectors.mapping((Map<String, Object> p) -> p, toList())));
By the way, there is no reason to copy the contents of mapList
into an array before creating the Stream
. You may simply call mapList.stream()
to get an appropriate Stream
.
Further, Collectors.mapping((Map<String, Object> p) -> p, toList())
is obsolete. p->p
is an identity mapping, so there’s no reason to request mapping
at all:
groupedResult = mapList.stream().collect(Collectors.groupingBy(
p -> new GroupingKey(p, groupByColumns), LinkedHashMap::new, toList()));
But even the GroupingKey
is obsolete. It basically wraps a List
of values, so you could just use a List
as key in the first place. List
s implement hashCode
and equals
appropriately (but you must not modify these key List
s afterwards).
Map<List<Object>, List<Object>> groupedResult=
mapList.stream().collect(Collectors.groupingBy(
p -> groupByColumns.stream().map(p::get).collect(toList()),
LinkedHashMap::new, toList()));
Based on @Holger's great answer. I post this to help those who want to keep the order after grouping as well as changing the mapping.
Let's simplify and suppose we have a list of persons (int age, String name, String adresss...etc) and we want the names grouped by age while keeping ages in order:
final LinkedHashMap<Integer, List<String> map = myList
.stream()
.sorted(Comparator.comparing(p -> p.getAge())) //sort list by ages
.collect(Collectors.groupingBy(p -> p.getAge()),
LinkedHashMap::new, //keeps the order
Collectors.mapping(p -> p.getName(), //map name
Collectors.toList())));