在日常的 Java 编码实践中,经常会遇到一个方法需要返回多个值的情况。例如,执行一个操作后,不仅要返回操作结果,还需附带状态码或额外描述信息。传统的解决方案,例如创建一个专用的数据传输对象(DTO)或使用 Map 集合,虽然可行,但往往会增加代码的复杂度,使调用方难以直观地理解和使用这些返回值。
此时,来自 Apache Commons Lang3 工具库的 org.apache.commons.lang3.tuple 包下的 Pair 和 Triple 类就成了简洁高效的替代方案。它们为管理和传递多个关联值提供了标准化的方式,能显著提升代码的清晰度和可维护性,是Java开发中处理简单数据组的实用工具。
引入依赖
使用 Pair 和 Triple 前,需在项目中引入 Apache Commons Lang3 库的依赖。在 Maven 项目中,于 pom.xml 文件中添加如下配置:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
Pair 类:便捷的键值对容器
Pair 类概述
Pair 是一个表示简单键值对的抽象类。它实现了 Map.Entry 接口,因此可以无缝用于各种集合操作;同时实现了 Comparable 接口,支持对象间的比较;并且它也是可序列化的。
以下是 Pair 类的部分核心源码:
public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {
public static <L, R> Pair<L, R> of(L left, R right) {
return ImmutablePair.of(left, right);
}
public static <L, R> Pair<L, R> of(Map.Entry<L, R> pair) {
return ImmutablePair.of(pair);
}
public final L getKey() {
return this.getLeft();
}
public abstract L getLeft();
public abstract R getRight();
public R getValue() {
return this.getRight();
}
}
Pair 类有两个直接的实现子类:MutablePair(可变)和 ImmutablePair(不可变)。
MutablePair:可变的键值对
MutablePair 允许在对象创建后修改其“左值”(left)和“右值”(right),提供了灵活性。但需要注意,它是非线程安全的。
创建方式示例:
// 方式1:使用构造方法
MutablePair<String, Integer> pair1 = new MutablePair<>("Key", 100);
// 方式2:使用静态工厂方法 of
MutablePair<String, Integer> pair2 = MutablePair.of("Key", 100);
// 方式3:创建空对象后设置值
MutablePair<String, Integer> pair3 = new MutablePair<>();
pair3.setLeft("Key");
pair3.setRight(100);
其左值和右值成员变量是 public 的,可直接访问 (pair.left, pair.right) 或通过 setLeft/setRight 方法修改。
ImmutablePair:不可变的键值对
ImmutablePair 在创建后其值不可更改,因此是线程安全的。尝试调用其 setValue 方法会抛出 UnsupportedOperationException 异常。
创建方式示例:
// 方式1:使用构造方法
ImmutablePair<String, Integer> pair1 = new ImmutablePair<>("Key", 100);
// 方式2:使用静态工厂方法 of (推荐)
ImmutablePair<String, Integer> pair2 = ImmutablePair.of("Key", 100);
// 方式3:通过 Pair 的静态工厂方法 of (返回的也是 ImmutablePair)
Pair<String, Integer> pair3 = Pair.of("Key", 100);
其成员变量同样为 public final,确保了一旦赋值便不可变。
Pair 使用示例
假设有一个 UserDO 类,我们定义一个方法根据用户ID查询用户信息并返回一个状态码。
class UserDO {
private String userId;
private Integer age;
// 省略getter/setter
}
// 业务方法:返回用户信息和查询状态
public Pair<UserDO, Integer> getUserInfoWithStatus(String userId) {
UserDO user = userDao.selectById(userId);
Integer status = (user != null) ? 200 : 404; // 200找到,404未找到
// 使用不可变Pair,确保返回结果不被意外修改
return ImmutablePair.of(user, status);
}
// 调用方
Pair<UserDO, Integer> result = getUserInfoWithStatus("123");
UserDO user = result.getLeft();
Integer statusCode = result.getRight();
// 或者使用 Map.Entry 接口定义的方法
UserDO user = result.getKey();
Integer statusCode = result.getValue();
// 尝试修改 ImmutablePair 的值会抛出异常
// result.setValue(500); // UnsupportedOperationException
Triple 类:强大的三元组工具
Triple 类概述
Triple 是一个用于表示三元组的抽象类,包含左(Left)、中(Middle)、右(Right)三个有序元素。它适用于需要返回三个紧密关联值的场景,避免了为简单组合而创建专门类的麻烦。
以下是 Triple 类的部分源码:
public abstract class Triple<L, M, R> implements Comparable<Triple<L, M, R>>, Serializable {
public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
return new ImmutableTriple<>(left, middle, right);
}
public abstract L getLeft();
public abstract M getMiddle();
public abstract R getRight();
}
Triple 同样有 MutableTriple 和 ImmutableTriple 两个子类。
MutableTriple:可变的三元组
MutableTriple 提供了 setLeft、setMiddle、setRight 方法用于修改其元素值,是非线程安全的。
// 创建可变三元组
MutableTriple<String, Integer, Boolean> triple = MutableTriple.of("Test", 1, true);
triple.setMiddle(2); // 修改中间值
ImmutableTriple:不可变的三元组
ImmutableTriple 是其不可变版本,线程安全。其三个成员变量均被声明为 final。
Triple 使用示例
考虑一个场景:执行一个批处理任务,需要返回成功数量、失败数量和总耗时。
class UserDO {
private String userId;
private String userName;
private Integer sex;
// 省略getter/setter
}
// 业务方法:批量处理用户,返回统计信息
public Triple<Integer, Integer, Long> batchProcessUsers(List<UserDO> users) {
long startTime = System.currentTimeMillis();
int success = 0;
int failure = 0;
for (UserDO user : users) {
boolean result = processSingleUser(user);
if (result) {
success++;
} else {
failure++;
}
}
long totalTime = System.currentTimeMillis() - startTime;
// 返回不可变三元组
return ImmutableTriple.of(success, failure, totalTime);
}
// 调用方
Triple<Integer, Integer, Long> stats = batchProcessUsers(userList);
int successCount = stats.getLeft();
int failureCount = stats.getMiddle();
long timeCost = stats.getRight();
System.out.printf("处理完成:成功%d条,失败%d条,耗时%dms%n", successCount, failureCount, timeCost);
总结
Pair 和 Triple 是 Apache Commons Lang3 中两个非常实用的工具类。它们通过提供标准化的轻量级容器,优雅地解决了方法多值返回的问题,减少了不必要的DTO类的创建,使代码意图更加清晰。ImmutablePair 和 ImmutableTriple 的不可变性也增强了代码在并发环境下的安全性。
在编码实践中,合理运用这些工具类能够有效简化数据结构处理,提升代码的可读性和可维护性。对于简单的、临时性的数据组合(尤其是作为方法返回值或局部变量),它们是优于自定义类或 Map 的简洁选择。然而,对于具有复杂行为或需要持久化的领域模型,定义完整的类仍然是更合适的做法。