Java 8 is not maintaining the order while grouping

collect, grouping, java-8, java-stream

Solution

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

Problem

I m using Java 8 for grouping by data. But results obtained are not in order formed. ``` Map<GroupingKey, List<Object>> groupedResult = null; if (!CollectionUtils.isEmpty(groupByColumns)) { Map<String, Object> mapArr[] = new LinkedHashMap[mapList.size()]; if (!CollectionUtils.isEmpty(mapList)) { int count = 0; for (LinkedHashMap<String, Object> map : mapList) { mapArr[count++] = map; } } Stream<Map<String, Object>> people = Stream.of(mapArr); groupedResult = people .collect(Collectors.groupingBy(p -> new GroupingKey(p, groupByColumns), Collectors.mapping((Map<String, Object> p) -> p, toList()))); public static class GroupingKey public GroupingKey(Map<String, Object> map, List<String> cols) { keys = new ArrayList<>(); for (String col : cols) { keys.add(map.get(col)); } } // Add appropriate isEqual() ... you IDE should generate this @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final GroupingKey other = (GroupingKey) obj; if (!Objects.equals(this.keys, other.keys)) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 37 * hash + Objects.hashCode(this.keys); return hash; } @Override public String toString() { return keys + ""; } public ArrayList<Object> getKeys() { return keys; } public void setKeys(ArrayList<Object> keys) { this.keys = keys; } } ``` Here i am using my class groupingKey by which i m dynamically passing from ux. How can get this groupByColumns in sorted form?

Original source