Java 中 List 分片的 5 种方法!
前些天在实现 MyBatis 批量插入时遇到了一个问题,当批量插入的数据量比较大时,会导致程序执行报错,如下图所示:

原因是 MySQL 只能执行一定长度的 SQL 语句,但当插入的数据量较多时,会生成一条很长的 SQL,这样程序在执行时就会报错。
要解决这个问题,有两种方法:第一,设置 MySQL 可以执行 SQL 的最大长度;第二,将一个大 List 分成 N 个小 List 进行。由于无法准确的界定程序中最大的 SQL 长度,所以最优的解决方案还是第二种,于是就有了今天的这篇文章。
简介
将一个 List 分成多个小 List 的过程,我们称之为分片,当然也可以叫做“List 分隔”,选一个你喜欢的、好理解的叫法就行。
在 Java 中,分片的常见实现方法有以下几种:
- 使用 Google 的 Guava 框架实现分片;
- 使用 Apache 的 commons 框架实现分片;
- 使用国产神级框架 Hutool 实现分片;
- 使用 JDK 8 中提供 Stream 实现分片;
- 自定义分片功能。
接下来我们分别来看。
1.Google Guava
先在项目的 pom.xml 中添加框架支持,增加以下配置:
<!-- google guava 工具类 -->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
有了 Guava 框架之后,只需要使用 Lists.partition 方法即可实现分片,如下代码所示:
import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.List;
/**
* Guava 分片
*/
public class PartitionByGuavaExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分片
List<List<String>> newList = Lists.partition(OLD_LIST, 3);
// 打印分片集合
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
以上代码的执行结果如下图所示:

2.apache commons
先在项目的 pom.xml 中添加框架支持,增加以下配置:
<!-- apache 集合工具类 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
有了 commons 框架之后,只需要使用 ListUtils.partition 方法即可实现分片,如下代码所示:
import org.apache.commons.collections4.ListUtils;
import java.util.Arrays;
import java.util.List;
/**
* commons.collections4 集合分片
*/
public class PartitionExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分片
List<List<String>> newList = ListUtils.partition(OLD_LIST, 3);
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
以上代码的执行结果如下图所示:

3.Hutool
先在项目的 pom.xml 中添加框架支持,增加以下配置:
<!-- 工具类 hutool -->
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.14</version>
</dependency>
有了 Hutool 框架之后,只需要使用 ListUtil.partition 方法即可实现分片,如下代码所示:
import cn.hutool.core.collection.ListUtil;
import java.util.Arrays;
import java.util.List;
public class PartitionByHutoolExample {
// 原集合
private static final List<String> OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 分片处理
List<List<String>> newList = ListUtil.partition(OLD_LIST, 3);
newList.forEach(i -> {
System.out.println("集合长度:" + i.size());
});
}
}
以上代码的执行结果如下图所示:

4.JDK
Stream
通过 JDK 8 中的 Stream 来实现分片就无需添加任何框架了,具体的实现代码如下:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* JDK Stream Partition
*/
public class PartitionByStreamExample {
// 原集合
private static final List<Integer> OLD_LIST = Arrays.asList(
1, 2, 3, 4, 5, 6);
public static void main(String[] args) {
// 集合分片:将大于 3 和小于等于 3 的数据分别分为两组
Map<Boolean, List<Integer>> newMap = OLD_LIST.stream().collect(
Collectors.partitioningBy(i -> i > 3)
);
// 打印结果
System.out.println(newMap);
}
}
以上代码的执行结果如下图所示:

此方式的优点的无需添加任何框架,但缺点是只能实现简单的分片(将一个 List 分为两个),并且要有明确的分片条件。比如本篇案例中设置的分片条件就是数组是否大于 3,如果大于 3 就会被归为一组,否则就会被分到另一组。
5.自定义分片
如果你不想引入第三方框架,并且使用 Stream 也无法满足你的需求,你就可以考虑自己写代码来实现分片功能了。因为此方式不常用,所以咱们这里只给出关键方法。
自定义分片功能的关键实现方法是 JDK 自带的 subList 方法,如下图所示:

使用示例如下:
import java.util.Arrays;
import java.util.List;
public class App {
private static final List<String> _OLD_LIST = Arrays.asList(
"唐僧,悟空,八戒,沙僧,曹操,刘备,孙权".split(","));
public static void main(String[] args) {
// 集合分隔
List<String> list = _OLD_LIST.subList(0, 3);
// 打印集合中的元素
list.forEach(i -> {
System.out.println(i);
});
}
}
以上代码的执行结果如下图所示:

总结
本文介绍了 5 种 List 分片的实现方法,其中最方便的实现方式是引入第三方框架,比如 Google 的 Guava、Apache 的 Commons 或者是国产开源的 Hutool 都可以,当然如果你的项目已经包含了以上任意一种,直接使用就行了。如果是简单的分片就可以考虑使用 JDK 的 Stream 或者是 List 内置的 subList 方法来实现分片功能了。
关注公众号「Java中文社群」查看更多 Java 总结性系列文章。
Java 中 List 分片的 5 种方法!的更多相关文章
- Java中创建数组的几种方法
Java中创建数组的几种方法 public static void main(String[] args) { //创建数组的第一种方法 int[] arr=new int[6]; int intVa ...
- 谈谈java中遍历Map的几种方法
java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下具体的用法以及各自的优缺点 先初始化一个map public ...
- Java中遍历map的四种方法 - 转载
在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...
- JAVA中创建线程的三种方法及比较
JAVA中创建线程的方式有三种,各有优缺点,具体如下: 一.继承Thread类来创建线程 1.创建一个任务类,继承Thread线程类,因为Thread类已经实现了Runnable接口,然后重写run( ...
- java中遍历map的几种方法介绍
喜欢用Java写程序的朋友都知道,我们常用的一种数据结构map中存储的是键值对,我们一般存储的方式是: map.put(key, value); 而提取相应键的值用的方法是: map.ge ...
- 干货 | Java中获取类名的3种方法!
获取类名的方法 Java 中获取类名的方式主要有以下三种. getName() 返回的是虚拟机里面的class的类名表现形式. getCanonicalName() 返回的是更容易理解的类名表示. g ...
- Java中终止线程的三种方法
终止线程一般建议采用的方法是让线程自行结束,进入Dead(死亡)状态,就是执行完run()方法.即如果想要停止一个线程的执行,就要提供某种方式让线程能够自动结束run()方法的执行.比如设置一个标志来 ...
- Java中List排序的3种方法
在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作.比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进 ...
- java中创建线程的几种方法及区别
1,实现Runnable接口创建线程 特点: A:将代码和数据分开,形成清晰的模型 B:线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法 C:有利于保持程序风格的一致性 2,继承Th ...
随机推荐
- 垃圾分类app--NABCD--团队项目需求与分析
我们的产品是--智能垃圾分类APP,它的设计灵感的来自于"可持续化发展战略,走绿色发展道路",众所周知,垃圾是放错了地方的资源,因此我们团队为了响应国家"垃圾分类&quo ...
- POJ 2509 Peter's smokes(Peter的香烟)
POJ 2509 Peter的香烟 描述 Peter抽烟.他抽烟一个个地抽着烟头.从 k (k>1) 个烟头中,他可以抽一根新烟.彼得可以抽几支烟? 输入 输入是一系列行.每行包含两个给出n和k ...
- PHP中的PDO操作学习(四)查询结构集
关于 PDO 的最后一篇文章,我们就以查询结果集的操作为结束.在数据库的操作中,查询往往占的比例非常高.在日常的开发中,大部分的业务都是读多写少型的业务,所以掌握好查询相关的操作是我们学习的重要内容. ...
- html2canvas实现截取指定区域或iframe的区域
官网文档: http://html2canvas.hertzen.com/ 使用的是 jquery 3.2.1 html2canvas 1.0.0-rc.7 截取根据id的指定区域: var ca ...
- js相同的正则多次调用test()返回的值却不同的问题
js代码: var name = '测试中文';// 姓名 var nameRgexp = new RegExp("[a-zA-Z\u4e00-\u9fa5]{2,}"," ...
- Redis Windows 服务启动异常 错误码1067
https://blog.csdn.net/after_you/article/details/62215163 Redis Windows 服务启动异常 错误码1067 下载了Redis 2.8.2 ...
- 『Python』matplotlib坐标轴应用
1. 设置坐标轴的位置和展示形式 import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl mpl.use ...
- 基于深度学习的建筑能耗预测01——Anaconda3-4.4.0+Tensorflow1.7+Python3.6+Pycharm安装
基于深度学习的建筑能耗预测-2021WS-02W 一,安装python及其环境的设置 (写python代码前,在电脑上安装相关必备的软件的过程称为环境搭建) · 完全可以先安装anaconda(会自带 ...
- Docker里面没有你期望的命令、甚至没有yum怎么办?
分享小知识点 跟大家分享一个实用的小知识点 有时候在docker容器里面不仅没有你期望的那些常用的命令,甚至没有yum命令让你去安装那些常用的命令 怎么办呢?不要慌! 没有yum命令说明这个容器的系统 ...
- MacOS上通过虚拟机搭建基础CentOS7系统环境
MacOS上通过虚拟机搭建基础CentOS7系统环境 尽管从Mac的Terminal可以看出,macOS与UNIX.Linux或多或少都有血缘关系(shell.bash等),但是在mac进行Linux ...