用Java對列表進行分區

1.概述

在本教程中,我將說明如何將列表拆分為給定大小的幾個子列表

對於相對簡單的操作,令人驚訝的是,標準Java集合API中沒有任何支持。幸運的是, GuavaApache Commons Collections都以類似的方式實現了該操作。

本文是Baeldung上“ Java – Back to Basic ”系列文章的一部分。

進一步閱讀:

在Java中將列表轉換為字符串

了解如何使用不同的技術將列表轉換為字符串。

閱讀更多→

在Java中改組集合

了解如何使用Java整理各種集合。

閱讀更多→

Java分離器簡介

了解可用於遍歷和分區序列的Spliterator接口。

閱讀更多→

2.使用番石榴對列表進行分區

Guava可通過**Lists.partition操作**方便地將List劃分為指定大小的子列表:

@Test

 public void givenList_whenParitioningIntoNSublists_thenCorrect() {

 List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

 List<List<Integer>> subSets = Lists.partition(intList, 3);



 List<Integer> lastPartition = subSets.get(2);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);

 assertThat(subSets.size(), equalTo(3));

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

3.使用番石榴對集合進行分區

番石榴也可以對集合進行分區

@Test

 public void givenCollection_whenParitioningIntoNSublists_thenCorrect() {

 Collection<Integer> intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);



 Iterable<List<Integer>> subSets = Iterables.partition(intCollection, 3);



 List<Integer> firstPartition = subSets.iterator().next();

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(1, 2, 3);

 assertThat(firstPartition, equalTo(expectedLastPartition));

 }

請記住,分區是原始集合的子列表視圖–這意味著原始集合中的更改將反映在分區中:

@Test

 public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() {

 // Given

 List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

 List<List<Integer>> subSets = Lists.partition(intList, 3);



 // When

 intList.add(9);



 // Then

 List<Integer> lastPartition = subSets.get(2);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8, 9);

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

4.使用Apache Commons集合對列表進行分區

最新版本的Apache Commons Collections 最近還增加了對List分區的支持:

@Test

 public void givenList_whenParitioningIntoNSublists_thenCorrect() {

 List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

 List<List<Integer>> subSets = ListUtils.partition(intList, 3);



 List<Integer> lastPartition = subSets.get(2);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);

 assertThat(subSets.size(), equalTo(3));

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

沒有相應的選項來對原始Collection進行分區-類似於Commons Collections中的Guava Iterables.partition。

最後,同樣的注意事項也適用於此處–所得分區是原始List的視圖。

5.使用Java8對列表進行分區

現在,讓我們看看如何使用Java8對List進行分區。

5.1。收藏家partitioningBy

我們可以使用Collectors.partitioningBy()將列表分為2個子列表–如下所示:

@Test

 public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() {

 List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);



 Map<Boolean, List<Integer>> groups =

 intList.stream().collect(Collectors.partitioningBy(s -> s > 6));

 List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());



 List<Integer> lastPartition = subSets.get(1);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);

 assertThat(subSets.size(), equalTo(2));

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

注意:生成的分區不是主列表的視圖,因此對主列表進行的任何更改都不會影響分區。

5.2。收藏家groupingBy

我們還可以使用Collectors.groupingBy()將列表拆分為多個分區:

@Test

 public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() {

 List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);



 Map<Integer, List<Integer>> groups =

 intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3));

 List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());



 List<Integer> lastPartition = subSets.get(2);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);

 assertThat(subSets.size(), equalTo(3));

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

注意:正如Collectors.partitioningBy() ,生成的分區將不受主List更改的影響。

5.3。按分隔符拆分列表

我們還可以使用Java8通過分隔符拆分List:

@Test

 public void givenList_whenSplittingBySeparator_thenCorrect() {

 List<Integer> 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<List<Integer>> subSets =

 IntStream.range(0, indexes.length - 1)

 .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))

 .collect(Collectors.toList());



 List<Integer> lastPartition = subSets.get(2);

 List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);

 assertThat(subSets.size(), equalTo(3));

 assertThat(lastPartition, equalTo(expectedLastPartition));

 }

注意:我們使用“ 0”作為分隔符–我們首先獲得列表中所有“ 0”元素的索引,然後在這些索引上拆分List

六,結論

這裡介紹的解決方案利用了其他庫– Guava或Apache Commons Collections庫。兩者都很輕巧,總體上非常有用,因此在類路徑中包含其中之一是很有意義的。但是,如果這不是一個選擇,請在此處顯示僅Java解決方案。

所有這些示例和代碼段的實現都**可以在GitHub上找到**-這是一個基於Maven的項目,因此應該很容易直接導入和運行。