Partitioniere eine Liste in Java

Partitionieren Sie eine Liste in Java

1. Überblick

In diesem Tutorial werde ichhow to split a List into several sublists einer bestimmten Größe veranschaulichen.

Für eine relativ einfache Operation gibt es überraschenderweise keine Unterstützung in den Standard-Java-Erfassungs-APIs. Glücklicherweise haben sowohlGuava als auchApache Commons Collections die Operation auf ähnliche Weise implementiert.

Dieser Artikel ist Teil vonthe “Java – Back to Basic” series hier am Beispiel.

Weitere Lektüre:

Konvertieren einer Liste in einen String in Java

Erfahren Sie, wie Sie eine Liste mithilfe verschiedener Techniken in einen String konvertieren.

Read more

Mischen von Sammlungen in Java

Erfahren Sie, wie Sie verschiedene Sammlungen in Java mischen.

Read more

Einführung in Spliterator in Java

Erfahren Sie mehr über die Spliterator-Oberfläche, die zum Durchlaufen und Aufteilen von Sequenzen verwendet werden kann.

Read more

2. Verwenden Sie Guave, um die Liste zu partitionieren

Guave erleichtert die Aufteilung der Liste in Unterlisten einer bestimmten Größe - überthe 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. Verwenden Sie Guava, um eine Sammlung zu partitionieren

Partitioning a Collection ist auch mit Guave möglich:

@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));
}

Beachten Sie, dass die Partitionensublist views of the original collection sind. Dies bedeutet, dass Änderungen in der ursprünglichen Sammlung in den Partitionen berücksichtigt werden:

@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. Verwenden Sie Apache Commons-Sammlungen, um die Liste zu partitionieren

Die neuesten Versionen von Apache Commons Collections unterstützenrecently addedauch beim Partitionieren einer 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));
}

Es gibtno corresponding option to partition a raw Collection - ähnlich der Guava Iterables.partition in Commons Collections.

Letztendlich gilt der gleiche Vorbehalt auch hier - die resultierende Partition sind Ansichten der ursprünglichen Liste.

5. Verwenden Sie Java8, um die Liste zu partitionieren

Lassen Sie uns nun sehen, wie Sie Java8 zum Partitionieren unserer Liste verwenden.

5.1. SammlerpartitioningBy

Wir könnenCollectors.partitioningBy() verwenden, um die Liste in 2 Unterlisten aufzuteilen - wie folgt:

@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));
}

Hinweis: Die resultierenden Partitionen sind keine Ansicht der Hauptliste, sodass Änderungen an der Hauptliste keine Auswirkungen auf die Partitionen haben.

5.2. SammlergroupingBy

Wir können auchCollectors.groupingBy() verwenden, um unsere Liste auf mehrere Partitionen aufzuteilen:

@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));
}

Hinweis: Genau wieCollectors.partitioningBy() werden die resultierenden Partitionen nicht von Änderungen in der Hauptliste beeinflusst.

5.3. Teilen Sie die Liste nach Trennzeichen

Wir können Java8 auch verwenden, um unsere Liste nach Trennzeichen zu teilen:

@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));
}

Hinweis: Wir haben "0" als Trennzeichen verwendet. Wir haben zuerst die Indizes aller "0" -Elemente in der Liste erhalten und dann dieList auf diesen Indizes aufgeteilt.

6. Fazit

Die hier vorgestellten Lösungen verwenden zusätzliche Bibliotheken - Guava oder die Apache Commons Collections-Bibliothek. Beide sind sehr leicht und insgesamt äußerst nützlich, daher ist es absolut sinnvoll, einen von ihnen auf dem Klassenpfad zu haben. Wenn dies jedoch keine Option ist - eine Nur-Java-Lösungis shown here.

Die Implementierung all dieser Beispiele und Codefragmentecan be found over on GitHub - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.