將一個list分紅多個list

將一個list或其餘集合按需分紅多份,例如,分批發送等,是很常見的需求,可是Java傳統的集合操做彷佛沒有提供這一支持。apache

幸虧,google guava 和apache commons collections都提供了相應的實現。數據結構

方法一:guava實現,將一個list按三個一組分紅N個小的list

代碼塊測試

[@Test](https://my.oschina.net/azibug)
​
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));
​
}

方法二:guava分割其餘collections

代碼塊google

[@Test](https://my.oschina.net/azibug)
​
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));
​
}

以上須要注意的是,partition返回的是原list的subview.視圖,也即,原list改變後,partition以後的結果也會隨着改變。.net

代碼塊code

[@Test](https://my.oschina.net/azibug)
​
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));
​
}

方法三:使用apache commons collection

代碼塊對象

[@Test](https://my.oschina.net/azibug)
​
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));
​
}
  1. 沒有對應的Iterable.partions方法,相似guava那樣
  2. partition後的結果一樣是原集合的視圖。

方法四:Java8方法。(在Java stream 中有講。)

a.經過grouping byget

代碼塊it

[@Test](https://my.oschina.net/azibug)
​
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));
​
}

按年齡分組:io

代碼塊

Map<Integer, List<Person>> personGroups = Stream.generate(new PersonSupplier()).
​
 limit(100).
​
 collect(Collectors.groupingBy(Person::getAge));
​
Iterator it = personGroups.entrySet().iterator();
​
while (it.hasNext()) {
​
 Map.Entry<Integer, List<Person>> persons = (Map.Entry) it.next();
​
 System.out.println("Age " + persons.getKey() + " = " + persons.getValue().size());
​
}

b.經過partition by

代碼塊

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

按照成年人與未成年人分組:

代碼塊

Map<Boolean, List<Person>> children = Stream.generate(new PersonSupplier()).
​
 limit(100).
​
 collect(Collectors.partitioningBy(p -> p.getAge() < 18));
​
System.out.println("Children number: " + children.get(true).size());
​
System.out.println("Adult number: " + children.get(false).size());

注意:

  1. Java8方式,分組後的list再也不是原list的視圖。因此,原list的改變不會影響分組後的結果。
  2. partitioningBy 實際上是一種特殊的 groupingBy,它依照條件測試的是否兩種結果來構造返回的數據結構,get(true) 和 get(false) 能即爲所有的元素對象
相關文章
相關標籤/搜索