Partitionner une liste en Java
1. Vue d'ensemble
Dans ce tutoriel, je vais illustrerhow to split a List into several sublists d'une taille donnée.
Pour une opération relativement simple, il n’ya étonnamment pas de prise en charge dans les API de collection Java standard. Heureusement, lesGuava et lesApache Commons Collections ont implémenté l'opération de la même manière.
Cet article fait partie dethe “Java – Back to Basic” series ici par exemple.
Lectures complémentaires:
Conversion d'une liste en chaîne en Java
Apprenez à convertir une liste en chaîne en utilisant différentes techniques.
Introduction à Spliterator en Java
En savoir plus sur l'interface Spliterator qui peut être utilisée pour les séquences de parcours et de partitionnement.
2. Utilisez Guava pour partitionner la liste
Guava facilite le partitionnement de la liste en sous-listes d'une taille spécifiée - viathe Lists.partition operation:
@Test
public void givenList_whenParitioningIntoNSublists_thenCorrect() {
List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
List> subSets = Lists.partition(intList, 3);
List lastPartition = subSets.get(2);
List expectedLastPartition = Lists. newArrayList(7, 8);
assertThat(subSets.size(), equalTo(3));
assertThat(lastPartition, equalTo(expectedLastPartition));
}
3. Utilisez Guava pour partitionner une collection
Partitioning a Collection est également possible avec Guava:
@Test
public void givenCollection_whenParitioningIntoNSublists_thenCorrect() {
Collection intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
Iterable> subSets = Iterables.partition(intCollection, 3);
List firstPartition = subSets.iterator().next();
List expectedLastPartition = Lists. newArrayList(1, 2, 3);
assertThat(firstPartition, equalTo(expectedLastPartition));
}
Gardez à l'esprit que les partitions sontsublist views of the original collection - ce qui signifie que les modifications de la collection d'origine seront reflétées dans les partitions:
@Test
public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() {
// Given
List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
List> subSets = Lists.partition(intList, 3);
// When
intList.add(9);
// Then
List lastPartition = subSets.get(2);
List expectedLastPartition = Lists. newArrayList(7, 8, 9);
assertThat(lastPartition, equalTo(expectedLastPartition));
}
4. Utiliser les collections Apache Commons pour partitionner la liste
Les dernières versions d'Apache Commons Collections prennent également en chargerecently added pour le partitionnement d'une liste:
@Test
public void givenList_whenParitioningIntoNSublists_thenCorrect() {
List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
List> subSets = ListUtils.partition(intList, 3);
List lastPartition = subSets.get(2);
List expectedLastPartition = Lists. newArrayList(7, 8);
assertThat(subSets.size(), equalTo(3));
assertThat(lastPartition, equalTo(expectedLastPartition));
}
Il y ano corresponding option to partition a raw Collection - similaire à la partition Guava Iterables.partition dans Commons Collections.
Enfin, la même mise en garde s'applique également ici: la partition résultante est une vue de la liste d'origine.
5. Utilisez Java8 pour partitionner la liste
Voyons maintenant comment utiliser Java8 pour partitionner notre liste.
5.1. CollecteurspartitioningBy
Nous pouvons utiliserCollectors.partitioningBy() pour diviser la liste en 2 sous-listes - comme suit:
@Test
public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() {
List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
Map> groups =
intList.stream().collect(Collectors.partitioningBy(s -> s > 6));
List> subSets = new ArrayList>(groups.values());
List lastPartition = subSets.get(1);
List expectedLastPartition = Lists. newArrayList(7, 8);
assertThat(subSets.size(), equalTo(2));
assertThat(lastPartition, equalTo(expectedLastPartition));
}
Remarque: les partitions résultantes ne sont pas une vue de la liste principale, donc toute modification apportée à la liste principale n’affectera pas les partitions.
5.2. CollecteursgroupingBy
Nous pouvons également utiliserCollectors.groupingBy() pour diviser notre liste en plusieurs partitions:
@Test
public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() {
List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
Map> groups =
intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3));
List> subSets = new ArrayList>(groups.values());
List lastPartition = subSets.get(2);
List expectedLastPartition = Lists. newArrayList(7, 8);
assertThat(subSets.size(), equalTo(3));
assertThat(lastPartition, equalTo(expectedLastPartition));
}
Remarque: tout commeCollectors.partitioningBy() - les partitions résultantes ne seront pas affectées par les modifications de la liste principale.
5.3. Diviser la liste par séparateur
Nous pouvons également utiliser Java8 pour scinder notre liste par séparateur:
@Test
public void givenList_whenSplittingBySeparator_thenCorrect() {
List intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8);
int[] indexes =
Stream.of(IntStream.of(-1), IntStream.range(0, intList.size())
.filter(i -> intList.get(i) == 0), IntStream.of(intList.size()))
.flatMapToInt(s -> s).toArray();
List> subSets =
IntStream.range(0, indexes.length - 1)
.mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))
.collect(Collectors.toList());
List lastPartition = subSets.get(2);
List expectedLastPartition = Lists. newArrayList(7, 8);
assertThat(subSets.size(), equalTo(3));
assertThat(lastPartition, equalTo(expectedLastPartition));
}
Remarque: Nous avons utilisé «0» comme séparateur - nous avons d'abord obtenu les indices de tous les éléments «0» de la liste, puis nous avons divisé lesList sur ces indices.
6. Conclusion
Les solutions présentées ici utilisent des bibliothèques supplémentaires - Guava ou la bibliothèque Apache Commons Collections. Les deux sont très légers et extrêmement utiles dans l'ensemble, il est donc parfaitement logique d'en avoir un sur le classpath; cependant, si ce n'est pas une option - une solution Java uniquementis shown here.
L'implémentation de tous ces exemples et extraits de codecan be found over on GitHub - c'est un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.