J'utilise Java 8 pour le regroupement par données. Mais les résultats obtenus ne sont pas classés dans l'ordre.
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;
}
}
Ici, j'utilise ma classe groupingKey par laquelle je passe dynamiquement de ux. Comment obtenir ce groupByColumns sous forme triée?
Le non-maintien de l'ordre est une propriété du Map
qui stocke le résultat. Si vous avez besoin d'un comportement Map
spécifique, vous devez demander une implémentation Map
particulière . Par exemple. LinkedHashMap
maintient l'ordre d'insertion:
groupedResult = people.collect(Collectors.groupingBy(
p -> new GroupingKey(p, groupByColumns),
LinkedHashMap::new,
Collectors.mapping((Map<String, Object> p) -> p, toList())));
Soit dit en passant, il n'y a aucune raison de copier le contenu de mapList
dans un tableau avant de créer le Stream
. Vous pouvez simplement appeler mapList.stream()
pour obtenir un Stream
approprié.
De plus, Collectors.mapping((Map<String, Object> p) -> p, toList())
est obsolète. p->p
Est un mappage d'identité, il n'y a donc aucune raison de demander mapping
:
groupedResult = mapList.stream().collect(Collectors.groupingBy(
p -> new GroupingKey(p, groupByColumns), LinkedHashMap::new, toList()));
Mais même le GroupingKey
est obsolète. Il enveloppe essentiellement un List
de valeurs, vous pouvez donc simplement utiliser un List
comme clé en premier lieu. List
s implémentent hashCode
et equals
de manière appropriée (mais vous ne devez pas modifier ces clés List
s après).
Map<List<Object>, List<Object>> groupedResult=
mapList.stream().collect(Collectors.groupingBy(
p -> groupByColumns.stream().map(p::get).collect(toList()),
LinkedHashMap::new, toList()));
Basé sur la grande réponse de @ Holger. Je poste ceci pour aider ceux qui veulent conserver l'ordre après le regroupement ainsi que la modification du mappage.
Simplifions et supposons que nous ayons une liste de personnes (int age, nom de chaîne, adresses de chaîne ... etc) et nous voulons que les noms soient groupés par âge tout en gardant les âges dans l'ordre:
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, //keep the order
Collectors.mapping(p -> p.getName(), //map name
Collectors.toList())));