一、概述
Pair 是 Apache Commons Lang3 提供的二元元组工具类,是 SpringBoot 项目中最常用的双值临时封装工具。
核心作用:一个方法需要返回两个不同结果,不想新建 DTO/VO 时,临时封装两个数据。
区别于 JDK 无原生 Pair,后端开发几乎统一使用 org.apache.commons.lang3.tuple.Pair。
二、项目依赖(SpringBoot)
SpringBoot 项目一般已自动引入,若无则手动添加:
xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
三、Pair 核心结构
3.1 核心包与类关系
- 核心抽象类:
org.apache.commons.lang3.tuple.Pair - 实现类:
ImmutablePair:不可变(默认推荐、线程安全)MutablePair:可变(可修改左右值)
3.2 核心方法
Pair.of(left, right):创建 Pair(默认返回不可变对象)getLeft():获取第一个元素getRight():获取第二个元素getKey():兼容 Map.Entry,等价 getLeftgetValue():兼容 Map.Entry,等价 getRight
四、基础用法演示
4.1 不可变 Pair(项目 99% 场景使用)
一旦创建,无法修改左右值,线程安全,规范推荐。
java
import org.apache.commons.lang3.tuple.Pair;
public class PairDemo {
public static void main(String[] args) {
// 创建二元组
Pair<String, Integer> user = Pair.of("张三", 20);
// 取值
String name = user.getLeft();
Integer age = user.getRight();
System.out.println(name); // 张三
System.out.println(age); // 20
}
}
4.2 可变 Pair(特殊场景使用)
支持动态修改左右值,非线程安全,仅局部临时使用。
java
import org.apache.commons.lang3.tuple.MutablePair;
public class MutablePairDemo {
public static void main(String[] args) {
MutablePair<String, Integer> pair = MutablePair.of("初始", 10);
// 修改值
pair.setLeft("修改后");
pair.setRight(20);
System.out.println(pair.getLeft()); // 修改后
System.out.println(pair.getRight()); // 20
}
}
五、企业级实战场景(高频)
场景1:方法返回「状态 + 提示信息」
业务层校验、登录、参数校验经典用法。
java
/**
* 用户名校验
* @return left: 是否成功 right: 提示信息
*/
public Pair<Boolean, String> checkUsername(String username) {
if (username == null || username.isBlank()) {
return Pair.of(false, "用户名不能为空");
}
if (username.length() < 2) {
return Pair.of(false, "用户名长度不能小于2位");
}
return Pair.of(true, "校验通过");
}
场景2:分页返回「列表 + 总条数」
无需新建分页临时 VO,内部逻辑极简封装。
java
public Pair<List<User>, Long> getUserPageList() {
List<User> userList = userMapper.selectList(null);
Long total = userMapper.selectCount(null);
return Pair.of(userList, total);
}
场景3:集合批量封装二元数据
java
List<Pair<String, Integer>> goodsList = new ArrayList<>();
goodsList.add(Pair.of("苹果", 10));
goodsList.add(Pair.of("香蕉", 20));
// 遍历
for (Pair<String, Integer> pair : goodsList) {
System.out.println("商品:" + pair.getLeft() + ",数量:" + pair.getRight());
}
六、核心对比:Pair vs Map vs DTO/VO
6.1 Pair vs Map(重点)
| 对比项 | Pair | Map |
|---|---|---|
| 存储结构 | 固定 2 个值(left/right) | Key-Value 动态多值集合 |
| 类型安全 | 泛型固定,无需强转 | Value 为 Object,需强转,不安全 |
| 可读性 | 一般(仅适合内部临时使用) | 差,依赖 key 字符串,易写错 |
| 性能 | 轻量、无哈希结构开销 | 重量级,适合大量数据存储 |
| 适用场景 | 方法返回两个固定结果 | 动态多键值、配置、字典数据 |
6.2 Pair vs 自定义 DTO/VO(开发核心规范)
| 对比项 | Pair | DTO/VO |
|---|---|---|
| 字段数量 | 固定 2 个,无法扩展 | 支持任意字段,可无限扩展 |
| 语义性 | 差,left/right 无业务含义 | 极强,自定义字段名见名知意 |
| 注解支持 | 不支持校验、文档注解 | 支持 @Data、@ApiModelProperty、校验注解 |
| 复用性 | 一次性临时使用 | 全局复用,统一业务规范 |
| 对外暴露 | 禁止在 Controller 返回 | 接口返回、跨模块传递首选 |
七、公司项目最佳实践(硬性规范)
✅ 允许使用 Pair 的场景
- 私有方法、内部工具方法临时返回两个值
- 一次性逻辑,无需复用、无需扩展
- 快速计算、临时数据封装,用完即弃
❌ 禁止使用 Pair 的场景
- Controller 接口返回给前端
- 公共方法、跨模块调用传参/返回值
- 未来可能新增字段的业务数据
- 需要文档、校验、序列化的正式数据
💡 终极选型口诀
- 内部临时双值、偷懒快速写 → Pair
- 对外暴露、长期维护、可扩展 → DTO/VO
- 多键值动态数据、配置存储 → Map
八、常见坑点避坑指南
- 默认 Pair 不可变:
Pair.of()返回 ImmutablePair,无法 set 赋值,需要修改必须用 MutablePair - 语义模糊:团队协作禁止用 Pair 传递核心业务数据,可读性极差
- 不可扩展:后续加字段必须重构代码,不如直接初始建 DTO
- 禁止接口返回:前端无法解析 left/right,无文档、无字段说明
九、拓展:Triple 三元组
需要临时返回三个值,可使用同包下的 Triple(left/middle/right),规则和 Pair 完全一致,同样只适合内部临时使用。