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. 使用场景

假设需要实现一个方法:根据输入返回 StringInteger

4.1. 传统 Java 实现

有两种实现方式:

  1. 返回 Map,用键标识成功/失败
  2. 返回固定大小 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 仓库


原始标题:Introduction to Vavr's Either