Regroupement et création d'une liste avec des clés en double en Java [duplicate]
Essaie de convertir List<Integer[]>à Map<Integer, List<Integer>>.
Donc, cela List<Integer[]>a des clés en double pour un exemple voir ci-dessous:
List<Integer[]> list = Arrays.asList(
new Integer[] {1, 23},
new Integer[] {2, 45},
new Integer[] {3, 25},
new Integer[] {1, 45},
new Integer[] {2, 54}
);
L'exigence est de convertir cela en carte ci-dessous où il regroupe par le 0ème index et de remettre toutes les valeurs sous la clé en double dans une sous-liste. Donc, finalement, ce serait quelque chose comme ça:
{1=[23, 45], 2=[45, 54], 3=[25]}
Je fais actuellement cela sans flux comme ci-dessous. Et je ne sais pas comment cela peut être réalisé avec Stream.
if (finalMap.containsKey(Integer.valueOf(dataList[0]))){
List<Integer> currentList = finalMap.get(Integer.valueOf(dataList[0]));
currentList.add(new Integer(Integer.valueOf(dataList[1])));
List<Integer> newList = new ArrayList<>(currentList);
finalMap.put(Integer.valueOf(dataList[0]), newList);
} else {
finalMap.put(
Integer.valueOf(dataList[0]),
new ArrayList<>(Arrays.asList(Integer.parseInt(dataList[1]))));
}
Réponses
Vous pouvez y parvenir en utilisant Collectors.groupingByle premier élément du tableau et utiliser un collecteur de mappage en aval pour obtenir les valeurs supplémentaires. Enfin, le plus en aval Collectors.toListenglobe les valeurs. Utilisez AbstractMap.SimpleEntrypour une meilleure manipulation avec les éléments du tableau.
Maintenant, la solution dépend uniquement, si chacun Integer[]contient exactement 2 éléments ou 2+ éléments :
Exactement 2 éléments dans chaque tableau
Chacun Integer[]contient toujours exactement deux éléments (ex. new Integer[] {1, 23}). Utilisez Collectors.mappingpour obtenir le résultat array[1](valeur de l'entrée) dans le fichier List.
Map<Integer, List<Integer>> map = list.stream()
.map(array -> new AbstractMap.SimpleEntry<>(array[0], array[1]))
.collect(Collectors.groupingBy(
AbstractMap.SimpleEntry::getKey,
Collectors.mapping(AbstractMap.SimpleEntry::getValue, Collectors.toList())));
En fait, l' SimpleEntryutilisation peut être omise et tout le flux simplifié si vous adressez directement les tableaux:
Map<Integer, List<Integer>> map = list.stream()
.collect(Collectors.groupingBy(
array -> array[0],
Collectors.mapping(array -> array[1], Collectors.toList())));
2+ éléments dans chaque tableau
Chacun Integer[]peut contenir deux éléments ou plus (ex. new Integer[] {1, 23, 24}). Utilisez Collectors.flatMappingpour obtenir les array[1].. array[n]items (valeur de l'entrée) dans le fichier List. N'oubliez pas que vous devez d'abord diviser le tableau pour effectuer le regroupement correct, par conséquent, le premier élément array[0]est la clé et array[1] .. array[n]sont des valeurs - c'est pourquoi le flatmapping est nécessaire.
Map<Integer, List<Integer>> map = list.stream()
.map(array -> new AbstractMap.SimpleEntry<>(
array[0],
Arrays.copyOfRange(array, 1, array.length)))
.collect(Collectors.groupingBy(
AbstractMap.SimpleEntry::getKey,
Collectors.flatMapping(
i -> Arrays.stream(i.getValue()),
Collectors.toList())));
Encore une fois, l'ensemble du flux peut être simplifié en omettant le SimpleEntrywrapper:
Map<Integer, List<Integer>> map = list.stream()
.collect(Collectors.groupingBy(
array -> array[0],
Collectors.flatMapping(
array -> Arrays.stream(Arrays.copyOfRange(array, 1, array.length)),
Collectors.toList())));
Par conséquent, grâce à l'obtention d'un sous-tableau qui peut résulter en un tableau vide, cette solution fonctionne également lorsqu'il y a au moins un élément présent dans le Integer[]tableau. Un résultat avec le tableau new Integer[] {3}dans l'entrée serait:
{1=[23, 45], 2=[45, 54, 88], 3=[]}
Avec Streams:
Map<Integer, List<Integer>> map =
dataList.stream().collect(Collectors.toMap(i -> i[0], i -> List.of(i[1]), (a, b) -> {
List<Integer> merged = new ArrayList<>(a);
merged.addAll(b);
return merged;
}));
Pour plus de lisibilité, je recommanderais que l'opération de fusion soit déplacée vers une méthode distincte. Vous pouvez également essayer d'obtenir le même résultat avec, groupingBymais c'est un peu plus difficile à obtenir lorsque vous utilisez des tableaux.
Voici la solution sans utiliser d'API tierce et sans utiliser de flux.
Integer [] array1 = {1, 23};
Integer [] array2 = {2, 45};
Integer [] array3 = {3, 25};
Integer [] array4 = {1, 45};
Integer [] array5 = {2, 54};
List<Integer[]> intlist = Arrays.asList( array1,array2,array3,array4,array5);
Map<Integer, List<Integer>> grouped = intlist.stream()
.collect(Collectors.groupingBy(arr -> arr[0],
Collectors.mapping(arr -> arr[1], Collectors.toList())));
System.out.println( grouped );
Produira
{1 = [23, 45], 2 = [45, 54], 3 = [25]}
comme demandé.