Java 8 no mantiene el orden mientras se agrupa

Estoy usando Java 8 para agrupar por datos. Pero los resultados obtenidos no están en orden formados.

Map<GroupingKey, List> groupedResult = null; if (!CollectionUtils.isEmpty(groupByColumns)) { Map mapArr[] = new LinkedHashMap[mapList.size()]; if (!CollectionUtils.isEmpty(mapList)) { int count = 0; for (LinkedHashMap map : mapList) { mapArr[count++] = map; } } Stream<Map> people = Stream.of(mapArr); groupedResult = people .collect(Collectors.groupingBy(p -> new GroupingKey(p, groupByColumns), Collectors.mapping((Map p) -> p, toList()))); public static class GroupingKey public GroupingKey(Map map, List 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 getKeys() { return keys; } public void setKeys(ArrayList keys) { this.keys = keys; } } 

Aquí estoy usando mi clase groupingKey por la cual estoy pasando dinámicamente desde ux. ¿Cómo puede obtener este groupByColumns en forma ordenada?

No mantener el orden es una propiedad del Map que almacena el resultado. Si necesita un comportamiento de Map específico, debe solicitar una implementación de Map particular . Por ejemplo, LinkedHashMap mantiene el orden de inserción:

 groupedResult = people.collect(Collectors.groupingBy( p -> new GroupingKey(p, groupByColumns), LinkedHashMap::new, Collectors.mapping((Map p) -> p, toList()))); 

Por cierto, no hay ninguna razón para copiar el contenido de mapList en una matriz antes de crear la Stream . Simplemente puede llamar a mapList.stream() para obtener un Stream apropiado.

Además, Collectors.mapping((Map p) -> p, toList()) está obsoleto. p->p es una asignación de identidad, por lo que no hay ninguna razón para solicitar la mapping en absoluto:

 groupedResult = mapList.stream().collect(Collectors.groupingBy( p -> new GroupingKey(p, groupByColumns), LinkedHashMap::new, toList())); 

Pero incluso el GroupingKey es obsoleto. Básicamente, envuelve una List de valores, por lo que podría usar una List como clave en primer lugar. List s implementar hashCode e equals apropiada (pero no debe modificar estas hashCode claves después).

 Map, List> groupedResult= mapList.stream().collect(Collectors.groupingBy( p -> groupByColumns.stream().map(p::get).collect(toList()), LinkedHashMap::new, toList())); 

Basado en la gran respuesta de @ Holger. Publico esto para ayudar a aquellos que quieren mantener el orden después de agruparlo y cambiar el mapeo.

Simplifiquemos y supongamos que tenemos una lista de personas (int., String name, String adresss … etc) y queremos que los nombres se agrupen por edad mientras se mantienen las edades en orden:

 final LinkedHashMap map = myList .stream() .sorted(Comparator.comparing(p -> p.getAge())) //sort list by ages .collect(Collectors.groupingBy(p -> p.getAge()), LinkedHashMap::new, //keep the order Collectors.mapping(p -> p.getName(), //map name Collectors.toList())));