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.
Mischen von Sammlungen in Java
Erfahren Sie, wie Sie verschiedene Sammlungen in Java mischen.
Einführung in Spliterator in Java
Erfahren Sie mehr über die Spliterator-Oberfläche, die zum Durchlaufen und Aufteilen von Sequenzen verwendet werden kann.
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.