1.概述
本快速教程将展示如何使用Java查找两个字符串之间的差异。
在本教程中,我们将使用两个现有的Java库,并比较它们解决此问题的方法。
2.问题
让我们考虑以下要求:我们想找到字符串" ABCDELMN"和" ABCFGLMN"之间的差异。
根据我们需要的输出格式,并忽略编写自定义代码的可能性,我们发现了两个主要选项。
第一个是Google编写的名为diff-match-patch的库。正如他们所声称的,该库提供了用于同步纯文本的强大算法。
另一个选项是Apache Commons Lang的StringUtilsclass。
让我们探讨一下两者之间的区别。
- diff-match-patch
出于本文的目的,我们将使用原始Google库的一个分支,因为原始库的构件未在Maven Central中发布。另外,某些类名称与原始代码库不同,并且更符合Java标准。
首先,我们需要在我们的pom.xml文件中包含其依赖项:
<dependency>
<groupId>org.bitbucket.cowwoc</groupId>
diff-match-patch</artifactId>
<version>1.2</version>
</dependency>
然后,让我们考虑以下代码:
String text1 ="ABCDELMN";
String text2 ="ABCFGLMN";
DiffMatchPatch dmp = new DiffMatchPatch();
LinkedList diff = dmp.diffMain(text1, text2, false);
如果运行上面的代码(这会在text1和text2之间产生差异),则打印变量diff将产生以下输出:
[Diff(EQUAL,"ABC"), Diff(DELETE,"DE"), Diff(INSERT,"FG"), Diff(EQUAL,"LMN")]
实际上,输出将是Diff对象的列表,每个对象由一种操作类型(INSERT,DELETE或EQUAL)以及与该操作相关联的文本部分组成。
当运行text2和text1之间的差异时,我们将得到以下结果:
[Diff(EQUAL,"ABC"), Diff(DELETE,"FG"), Diff(INSERT,"DE"), Diff(EQUAL,"LMN")]
- StringUtils
Apache Commons中的类具有更简单的方法。
首先,我们将Apache Commons Lang依赖项添加到我们的pom.xml文件中:
<dependency>
<groupId>org.apache.commons</groupId>
commons-lang3</artifactId>
<version>3.9</version>
</dependency>
然后,要使用Apache Commons查找两个文本之间的差异,我们将其称为StringUtils#Difference:
StringUtils.difference(text1, text2)
产生的输出将是一个简单的字符串:
FGLMN
而运行text2和text1之间的差异将返回:
DELMN
可以使用StringUtils.indexOfDifference()增强此简单方法,该函数将返回两个字符串开始不同的索引(在本例中为该字符串的第四个字符)。该索引可用于获取原始字符串的子字符串,以显示两个输入之间的共同点以及区别。
5.表现
对于我们的基准测试,我们生成了10,000个字符串列表,其中固定部分包含10个字符,然后是20个随机字母字符。
然后,我们遍历列表,并在列表的第n个元素和第n + 1个元素之间进行比较:
@Benchmark
public int diffMatchPatch() {
for (int i = 0; i < inputs.size() - 1; i++) {
diffMatchPatch.diffMain(inputs.get(i), inputs.get(i + 1), false);
}
return inputs.size();
}
@Benchmark
public int stringUtils() {
for (int i = 0; i < inputs.size() - 1; i++) {
StringUtils.difference(inputs.get(i), inputs.get(i + 1));
}
return inputs.size();
}
最后,让我们运行基准测试并比较两个库:
Benchmark Mode Cnt Score Error Units
StringDiffBenchmarkUnitTest.diffMatchPatch avgt 50 130.559 ± 1.501 ms/op
StringDiffBenchmarkUnitTest.stringUtils avgt 50 0.211 ± 0.003 ms/op
六,结论
就纯执行速度而言,尽管StringUtils仅返回两个字符串开始有所不同的子字符串,但显然性能更高。
同时,Diff-Match-Patch提供更全面的比较结果,但会降低性能。
这些示例和代码片段的实现可从GitHub上获得。
原文连接:点击进入
文章评论