目录
前言
在日常开发中,我们经常需要将一个大的列表(List)按固定大小切分成多个子列表,用于批量插入数据库、分页请求、限制 API 调用参数数量等场景。手动编写分片逻辑不仅繁琐,还容易出错。
幸运的是,Google Guava 库 提供了一个极其简洁且高效的工具方法:Lists.partition(),一行代码即可完成分批操作。
什么是 Lists.partition()?
Lists.partition() 是 Guava 中 com.google.common.collect.Lists 类提供的静态方法,用于将一个 List 按指定大小分割成多个子列表。
方法签名
public static List<List> partition(List list, int size)
参数说明
| 参数 | 说明 |
|---|---|
| list | 要被分割的原始列表(不可为 null) |
| size | 每个子列表的最大元素个数(必须 > 0) |
返回值
- 返回 List>:一个"列表的列表"。
- 每个内层子列表最多包含 size 个元素。
- 最后一个子列表可能小于 size。
- 返回的是视图(view),不是深拷贝(但通常只读使用,安全)。
依赖
xml
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
示例 一
分批处理 List
假设你有 7 个学生对象,需要每批处理 3 个(例如批量插入数据库):
java
public class Student {
String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
java
import com.google.common.collect.Lists;
import java.util.List;
public class BatchProcessingExample {
public static void main(String[] args) {
// 构造学生列表
List<Student> students = new ArrayList<>();
students.add(new Student("Alice"));
students.add(new Student("Bob"));
students.add(new Student("Charlie"));
students.add(new Student("David"));
students.add(new Student("Eve"));
students.add(new Student("Frank"));
students.add(new Student("Grace"));
final int BATCH_SIZE = 3;
List<List<Student>> batches = Lists.partition(students, BATCH_SIZE);
for (int i = 0; i < batches.size(); i++) {
System.out.println("批次 " + (i + 1) + ":"+batches.get(i));
}
}
}
输出:
java
批次 1:[Alice, Bob, Charlie]
批次 2:[David, Eve, Frank]
批次 3:[Grace]
示例二
将字符串 ID 列表每 4 个分一组,用于 SQL 的 IN 查询(避免超过数据库限制):
java
import com.google.common.collect.Lists;
import java.util.List;
public class StringBatchExample {
public static void main(String[] args) {
List<String> ids = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
List<List<String>> partitions = Lists.partition(ids, 4);
// 模拟分批查询
partitions.forEach(batch ->
System.out.println("SELECT * FROM users WHERE id IN (" + String.join(",", batch) + ")")
);
}
}
输出结果
java
SELECT * FROM users WHERE id IN (A,B,C,D)
SELECT * FROM users WHERE id IN (E,F,G)
适用场景
- 数据库 IN 查询分批(如 MySQL 单次 IN 建议不超过 1000 项)
- 批量删除、更新操作
- 分块处理日志或文件行
注意事项
- 时区无关:Lists.partition() 只做结构分割,与数据内容无关。
- 不可变性:返回的子列表是原列表的视图,如果原列表被修改,分区结果也会变化(建议对不可变列表使用)。
- 空列表处理:若输入元素个数为0的空列表,返回一个包含一个空子列表的列表[],即最外层List的size为0。
- 性能高效:内部使用 AbstractList 实现,无额外内存拷贝。
对比:不用 Guava 怎么做?
若不使用 Guava,需手动循环分片:
java
List<List<Student>> manualBatches = new ArrayList<>();
for (int i = 0; i < students.size(); i += batchSize) {
manualBatches.add(students.subList(i, Math.min(i + batchSize, students.size())));
}
总结
Lists.partition(list, size) 是处理分批任务的利器:
一行代码,安全高效地将大列表切分为固定大小的小批次。
无论是 List 、 List 还是其他类型,它都能以泛型方式完美适配。在涉及批量操作的场景中,强烈推荐使用此方法提升代码质量与开发效率。
小贴士: 如果你的项目已使用 Spring、Hutool 或 Apache Commons,它们也提供了类似功能,但 Guava 的 partition 仍是 Java 社区最广泛认可的实现之一。