1. 简介

Cactoos 是一个面向对象风格的 Java 基元类型库,它的设计哲学是“一切皆对象”,避免使用静态工具类和过程式编程惯用法。

本文将带你了解 Cactoos 提供的一些核心类,帮助你在项目中更优雅地处理字符串、集合等常见操作。✅

⚠️ 注意:Cactoos 并不是为了替代 Guava 或 Apache Commons,而是提供一种更符合 OOP 和函数式风格的编程方式。

2. Cactoos 核心理念

Cactoos 覆盖了从字符串处理到数据结构、IO、日期时间等多个领域。它提供的功能与 GuavaApache Commons 类似,但更强调面向对象设计原则(如 SOLID),尤其是:

  • 消除 null
  • 避免副作用
  • 所有操作都是不可变的(immutable)
  • 使用组合而非继承

2.1 与 Apache Commons 的对比

Cactoos 用“对象”替代了 Apache Commons 中常见的“静态方法”。这种转变让代码更具可读性和可测试性。

下面是 StringUtils 中常用静态方法与 Cactoos 对应类的对照表:

StringUtils 静态方法 Cactoos 等价类
isBlank() IsBlank
lowerCase() Lowered
upperCase() Upper
rotate() Rotated
swapCase() SwappedCase
stripStart() TrimmedLeft
stripEnd() TrimmedRight

📌 官方文档中有更完整的对照表:Our Objects vs Their Static Methods

接下来我们通过实际代码看看这些类怎么用。

3. Maven 依赖

使用前先引入依赖。最新版本可在 Maven Central 查询:

<dependency>
    <groupId>org.cactoos</groupId>
    <artifactId>cactoos</artifactId>
    <version>0.55.0</version>
</dependency>

✅ 推荐使用较新版本,避免已知 bug。

4. 字符串操作

Cactoos 提供了丰富的字符串处理类,全部基于 Text 接口。

4.1 创建字符串对象

使用 TextOf 包装原始字符串:

String testString = new TextOf("Test String").asString();

💡 TextOf 是最基础的文本包装类,几乎所有字符串操作都基于它。

4.2 格式化字符串

FormattedText 实现 String.format 的功能:

String formattedString = new FormattedText("Hello %s", stringToFormat).asString();

测试示例:

StringMethods obj = new StringMethods();

String formattedString = obj.createdFormattedString("John");
assertEquals("Hello John", formattedString);

4.3 转换大小写

  • 转小写:Lowered
  • 转大写:Upper
String lowerCaseString = new Lowered(new TextOf(testString)).asString();

String upperCaseString = new Upper(new TextOf(testString)).asString();

验证示例:

StringMethods obj = new StringMethods();

String lowerCaseString = obj.toLowerCase("TeSt StrIng");
String upperCaseString = obj.toUpperCase("TeSt StrIng"); 

assertEquals("test string", lowerCaseString);
assertEquals("TEST STRING", upperCaseString);

✅ 这种链式写法虽然略 verbose,但好处是类型安全、易于 mock 和测试。

4.4 判断空字符串

使用 IsBlank 替代 StringUtils.isBlank()

boolean isBlank = new IsBlank(new TextOf(testString)).value();

⚠️ 注意:IsBlank 返回的是 Scalar<Boolean>,需要调用 .value() 获取实际值。

正确写法应该是:

assertTrue(new IsBlank(new TextOf("")).value());
assertFalse(new IsBlank(new TextOf("hello")).value());

5. 集合操作

Cactoos 对集合的操作也完全对象化,避免使用 for 循环或 Stream 的副作用。

5.1 遍历集合

使用 And + Mapped 实现无副作用的遍历(类似 forEach):

new And(
  new Mapped<>(
    new FuncOf<>(
      input -> System.out.printf("Item: %s\n", input),
      new True()
    ),
    strings
  )
).value();

❌ 踩坑提醒:And 通常用于布尔组合,这里用于副作用操作其实有点“歪楼”,但确实能跑通。更推荐使用 IoCheckedProc 或自定义 Proc

5.2 过滤集合

使用 Filtered 对集合进行过滤:

public Collection<String> getFilteredList(List<String> strings) {
    return new ListOf<>(
      new Filtered<>(
        s -> s.length() == 5,
        strings
      )
    );
}

测试用例:

CollectionUtils obj = new CollectionUtils(); 

List<String> strings = new ArrayList<>();
strings.add("Hello"); 
strings.add("John");
strings.add("Smith"); 
strings.add("Eric"); 
strings.add("Dizzy"); 

int size = obj.getFilteredList(strings).size(); 

assertEquals(3, size);

✅ 匹配项为:"Hello"、"Smith"、"Dizzy"

更多集合相关类可参考官方文档:Iterables/Collections/Lists/Sets

6. 总结

Cactoos 提供了一种完全对象化的 Java 编程方式,适用于追求高可读性、低副作用、强可测性的项目。

除了本文介绍的字符串和集合操作,它还支持:

  • ✅ IO 操作:InputOutputBytesText
  • ✅ 日期时间:NowAgeElapsed
  • ✅ 并发:SyncScalarIoCheckedScalar

📌 适用场景:

  • 团队强调函数式 + OOP 风格
  • 想减少 null 和静态工具类滥用
  • 需要高度可测试的代码

⚠️ 注意事项:

  • 性能开销略高(对象创建频繁)
  • 学习曲线较陡,团队需统一认知
  • 社区活跃度不如 Guava

所有示例代码已托管至 GitHub:https://github.com/tech-tutorial/tutorials/tree/master/libraries-data-3


原始标题:Cactoos