将一个list分成多个list的Java实现。

本文介绍如何使用Guava和Apache Commons Collections库将Java集合按需分割成子集合的方法,并展示了如何利用Java 8 Stream API进行分组和条件分割的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将一个list或其他集合按需分成多份,例如,分批发送等。是很常见的需求。但是Java传统的集合操作似乎没有提供这一支持。幸好,google guava 和apache commons collections都提供了相应的实现。

方法一:guava实现,将一个list按三个一组分成N个小的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));
}

方法二:guava分割其他collections

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


以上需要注意的是,partition返回的是原list的subview.视图,也即,原list改变后,partition之后的结果也会随着改变。

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


方法三:使用apache commons collection

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

1.没有对应的Iterable.partions方法,类似guava那样

2.partition后的结果同样是原集合的视图。

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

a.通过grouping by 

@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));
}
按年龄分组:
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的改变不会影响分组后的结果。

2partitioningBy 其实是一种特殊的 groupingBy,它依照条件测试的是否两种结果来构造返回的数据结构,get(true) 和 get(false) 能即为全部的元素对象

### Java 分组 List 中相同的元素到不同的子列表 为了将包含重复值的 `List` 根据相同值分割成多个子 `List`,可以利用 Java 的流(Stream API)以及收集器(Collectors)。具体来说,通过使用 `groupingBy` 方法可以根据特定条件对数据进行分组。 下面是一个完整的例子来展示如何实现这一功能: ```java import java.util.*; import java.util.stream.Collectors; public class GroupElements { public static void main(String[] args) { // 创建一个包含重复字符串的列表 List<String> originalList = Arrays.asList("apple", "banana", "orange", "apple", "grape", "banana"); // 使用stream和collect方法按照元素本身进行分组 Map<String, List<String>> groupedMap = originalList.stream() .collect(Collectors.groupingBy(e -> e)); // 打印结果 System.out.println(groupedMap); // 如果只需要子列表而不需要键,则可以通过values()获得这些子列表 List<List<String>> subLists = new ArrayList<>(groupedMap.values()); System.out.println(subLists); } } ``` 上述代码首先定义了一个含有重复项的字符串列表 `originalList`。接着调用了 `.stream()` 将其转换为流形式,并应用了 `Collectors.groupingBy` 来依据元素本身的值来进行分组[^1]。最终得到的结果是以原始元素作为 key 的映射表,其中 value 是由具有相同 key 值的所有实例组成的列表。如果只关心各个分组后的子列表而不关注它们对应的 key,那么可以从映射中提取所有的 values 即可[^3]。 对于更复杂的情况,比如当处理的是自定义对象而非简单类型时,也可以采用类似的逻辑,只需调整 `groupingBy` 函数内的分类标准即可。例如,在学生信息的例子中提到过基于性别对学生记录进行分组的操作[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值