1. 概述
Vavr 是一个面向 Java 8+ 的开源对象函数式扩展库。它能有效减少代码量并提升程序健壮性。
本文将深入探讨 Vavr 的核心工具 Either。若想系统学习 Vavr 库,可参考这篇教程。
2. 什么是 Either?
在函数式编程中,函数值或对象不可修改(即处于标准形式)。用 Java 术语说,就是不可变对象。
Either 表示两种可能数据类型的值。一个 Either 要么是 Left 要么是 *Right*。按约定:
- Left 表示失败结果
- Right 表示成功结果
3. Maven 依赖
在 pom.xml
中添加以下依赖:
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.9.0</version>
</dependency>
最新版本可在 Maven 中央仓库 获取。
4. 使用场景
假设需要实现一个方法:根据输入返回 String
或 Integer
。
4.1. 传统 Java 实现
有两种实现方式:
- 返回 Map,用键标识成功/失败
- 返回固定大小 List/Array,用位置标识结果类型
Map 实现示例:
public static Map<String, Object> computeWithoutEitherUsingMap(int marks) {
Map<String, Object> results = new HashMap<>();
if (marks < 85) {
results.put("FAILURE", "Marks not acceptable");
} else {
results.put("SUCCESS", marks);
}
return results;
}
public static void main(String[] args) {
Map<String, Object> results = computeWithoutEitherUsingMap(8);
String error = (String) results.get("FAILURE");
int marks = (int) results.get("SUCCESS");
}
Array 实现示例:
public static Object[] computeWithoutEitherUsingArray(int marks) {
Object[] results = new Object[2];
if (marks < 85) {
results[0] = "Marks not acceptable";
} else {
results[1] = marks;
}
return results;
}
⚠️ 这两种方式都存在明显缺陷:
- 需要大量样板代码
- 类型安全性差(强制类型转换)
- 代码可读性低
4.2. 使用 Either
现在用 Vavr 的 Either 重写:
private static Either<String, Integer> computeWithEither(int marks) {
if (marks < 85) {
return Either.left("Marks not acceptable");
} else {
return Either.right(marks);
}
}
✅ 优势立现:
- 无需显式类型转换
- 无需空值检查
- 无需创建冗余对象
Either 还提供类 Monad 的链式 API:
computeWithEither(80)
.right()
.filter(...)
.map(...)
// ...
核心约定:
- Left = 失败
- Right = 成功
但 Vavr 的 Either 并不偏向 Left/Right,可通过投影(Projection)灵活切换:
Right 投影示例:
computeWithEither(90).right()
.filter(...)
.map(...)
.getOrElse(Collections::emptyList);
❌ 若实际是 Left,操作立即返回空列表
Left 投影示例:
computeWithEither(9).left()
.map(FetchError::getMsg)
.forEach(System.out::println);
4.3. 高级特性
Either 提供丰富实用方法:
类型判断:
result.isLeft(); // 是否为 Left
result.isRight(); // 是否为 Right
值包含检查:
result.contains(100) // 是否包含指定 Right 值
折叠(Fold)操作:
Either<String, Integer> either = Either.right(42);
String result = either.fold(i -> i, Object::toString);
左右交换:
Either<String, Integer> either = Either.right(42);
Either<Integer, String> swap = either.swap();
5. 总结
本文系统介绍了 Vavr 框架中 Either 的核心用法。更多细节可参考官方文档。
完整源码见 GitHub 仓库。