Partitionner une liste en Java

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.

Read more

Mélanger les collections en Java

Apprenez à mélanger diverses collections en Java.

Read more

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.

Read more

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.