1. 概述

简单来说,Apache Commons Text 库提供了一系列实用的字符串处理工具,弥补了 Java 核心库的不足。本文将快速介绍这个库的核心功能和使用场景,并通过实际代码演示其强大之处。

2. Maven 依赖

首先在 pom.xml 中添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.10</version>
</dependency>

最新版本可在 Maven 中央仓库 查找。

3. 包结构概览

库的核心包 org.apache.commons.text 包含三个子包,各司其职:

  • org.apache.commons.text.diff → 字符串差异计算
  • org.apache.commons.text.similarity → 字符串相似度与距离分析
  • org.apache.commons.text.translate → 文本转换处理

下面我们逐一拆解这些包的实用功能。

4. 文本处理

org.apache.commons.text 包提供了丰富的字符串操作工具:

4.1 WordUtils 实战

单词首字母大写

@Test
public void whenCapitalized_thenCorrect() {
    String toBeCapitalized = "to be capitalized!";
    String result = WordUtils.capitalize(toBeCapitalized);
    
    assertEquals("To Be Capitalized!", result);
}

检查字符串是否包含指定单词

@Test
public void whenContainsWords_thenCorrect() {
    boolean containsWords = WordUtils
      .containsAllWords("String to search", "to", "search");
    
    assertTrue(containsWords);
}

4.2 StrSubstitutor 模板引擎

简单粗暴的字符串模板替换方案:

@Test
public void whenSubstituted_thenCorrect() {
    Map<String, String> substitutes = new HashMap<>();
    substitutes.put("name", "John");
    substitutes.put("college", "University of Stanford");
    String templateString = "My name is ${name} and I am a student at the ${college}.";
    StrSubstitutor sub = new StrSubstitutor(substitutes);
    String result = sub.replace(templateString);
    
    assertEquals("My name is John and I am a student at the University of Stanford.", result);
}

4.3 StrBuilder 增强版字符串构建器

StringBuilder 更强大的替代方案:

@Test
public void whenReplaced_thenCorrect() {
    StrBuilder strBuilder = new StrBuilder("example StrBuilder!");
    strBuilder.replaceAll("example", "new");
   
    assertEquals(new StrBuilder("new StrBuilder!"), strBuilder);
}

⚠️ 清空字符串无需重新赋值

strBuilder.clear();  // 直接清空,避免创建新对象

5. 计算字符串差异

org.apache.commons.text.diff 包实现了 Myers 算法,用于计算两个字符串的差异。差异被定义为将一个字符串转换为另一个所需的修改序列

核心修改命令包括:

  • InsertCommand → 插入字符
  • KeepCommand → 保留字符
  • DeleteCommand → 删除字符

通过 EditScript 获取修改脚本:

@Test
public void whenEditScript_thenCorrect() {
    StringsComparator cmp = new StringsComparator("ABCFGH", "BCDEFG");
    EditScript<Character> script = cmp.getScript();
    int mod = script.getModifications();
    
    assertEquals(4, mod);  // 需要执行4次单字符修改
}

6. 字符串相似度与距离

org.apache.commons.text.similarity 包提供多种相似度算法:

6.1 最长公共子序列 (LCS)

计算两个字符串的公共字符数:

@Test
public void whenCompare_thenCorrect() {
    LongestCommonSubsequence lcs = new LongestCommonSubsequence();
    int countLcs = lcs.apply("New York", "New Hampshire");
    
    assertEquals(5, countLcs);  // "New " + "H" (注意空格也算字符)
}

6.2 LCS 距离

计算不同字符的数量:

@Test
public void whenCalculateDistance_thenCorrect() {
    LongestCommonSubsequenceDistance lcsd = new LongestCommonSubsequenceDistance();
    int countLcsd = lcsd.apply("New York", "New Hampshire");
    
    assertEquals(11, countLcsd);  // 总长度差 + 非公共字符
}

7. 文本转换

org.apache.text.translate 包最初用于扩展 StringEscapeUtils 的功能,支持多种编码转换:

7.1 Unicode 转义

将字符串转换为 Unicode 表示:

@Test
public void whenTranslate_thenCorrect() {
    UnicodeEscaper ue = UnicodeEscaper.above(0);  // 从索引0开始转换
    String result = ue.translate("ABCD");
    
    assertEquals("\\u0041\\u0042\\u0043\\u0044", result);
}

7.2 自定义查找表

通过 LookupTranslator 实现字符映射转换:

// 示例:创建自定义转换规则
Map<CharSequence, CharSequence> mapping = new HashMap<>();
mapping.put("foo", "bar");
LookupTranslator translator = new LookupTranslator(mapping);
String result = translator.translate("foo is foo");
// 输出: "bar is bar"

8. 总结

Apache Commons Text 是处理字符串的瑞士军刀,尤其擅长:

  • 模板字符串替换(StrSubstitutor
  • 增强字符串构建(StrBuilder
  • 文本差异分析(diff 包)
  • 相似度计算(similarity 包)
  • 编码转换(translate 包)

完整代码示例可在 GitHub 获取。踩坑提示:使用相似度算法时注意空格和大小写的影响!


原始标题:Introduction to Apache Commons Text