如何在Java中执行字符串差异比较?

58

我需要在Java字符串之间执行差异比较。我想要能够使用原始字符串和差异版本重建一个字符串。有没有人在Java中做过这个?你使用什么库?

String a1; // This can be a long text
String a2; // ej. above text with spelling corrections
String a3; // ej. above text with spelling corrections and an additional sentence

Diff diff = new Diff();
String differences_a1_a2 = Diff.getDifferences(a,changed_a);
String differences_a2_a3 = Diff.getDifferences(a,changed_a);    
String[] diffs = new String[]{a,differences_a1_a2,differences_a2_a3};
String new_a3 = Diff.build(diffs);
a3.equals(new_a3); // this is true

另请参见https://dev59.com/YHRB5IYBdhLWcg3w4bEo - Stewart
9个回答

55

这些是不同的库,顺便说一下。 - Kerinin
6
Google-diff-match-patch的Maven仓库在这里 - fracz
5
java-diff-utils的活跃维护分支似乎是https://github.com/bkromhout/java-diff-utils。 - koppor
在Github上的google-diff-match-patch:https://github.com/GerHobbelt/google-diff-match-patch - isapir
2
维护的分支似乎现在是 https://github.com/java-diff-utils/java-diff-utils。 - golimar

27

Apache Commons 提供了字符串比较功能

org.apache.commons.lang.StringUtils

StringUtils.difference("foobar", "foo");

7
这个方法返回第二个字符串中与第一个字符串不同部分的余下部分。但对我来说效率不够,因为我要处理大文本。举个例子: StringUtils.difference("ab", "abxyz") -> "xyz" StringUtils.difference("ab", "xyzab") -> "xyzab"。 - Sergio del Amo
3
还要注意这个问题: StringUtils.difference("abc", "") = "" StringUtils.difference("abc", "abc") = "" - Alec

4

3
这个仓库 https://github.com/bkromhout/java-diff-utils/ 是间接从原始的GitHub代码库进行了派生并得到更好的维护。也许你可以在那里加入力量? - koppor

3
如Torsten所说,你可以使用org.apache.commons.lang.StringUtils;
System.err.println(StringUtils.getLevenshteinDistance("foobar", "bar"));

谢谢,但 getLevenshteinDistance 只返回一个整数。这不足以重建字符串。 - Hans-Peter Störr
@hstoerr,你说得对,我可能错过了原始问题中的这一部分。现在已经是很久以前的事情了 :) - Paul Whelan
那个方法也已经过时了。 - Constantino Cronemberger

1
如果您需要处理大量数据之间的差异并高效压缩这些差异,您可以尝试使用Java实现的xdelta,它反过来实现了RFC 3284(VCDIFF)用于二进制差异(也应该适用于字符串)。

0

使用Levenshtein距离并从算法构建的矩阵中提取编辑日志。维基百科文章链接到几个实现,我相信其中有一个Java实现。

Levenshtein是最长公共子序列算法的特例,您可能还想查看一下。


0
我发现在回归测试中,如果我不需要在生产环境中进行差异支持,使用 assertj 提供的内置访问 java-diff-utils 是非常有用的。例如,可以查看其 DiffUtils、InputStream 或 Diff 类。

0

Apache Commons Text现在有StringsComparator

StringsComparator c = new StringsComparator(s1, s2);
c.getScript().visit(new CommandVisitor<Character>() {

    @Override
    public void visitKeepCommand(Character object) {
        System.out.println("k: " + object);
    }

    @Override
    public void visitInsertCommand(Character object) {
        System.out.println("i: " + object);
    }

    @Override
    public void visitDeleteCommand(Character object) {
        System.out.println("d: " + object);
    }
});

-7
public class Stringdiff {
public static void main(String args[]){
System.out.println(strcheck("sum","sumsum"));
}
public static String strcheck(String str1,String str2){
    if(Math.abs((str1.length()-str2.length()))==-1){
        return "Invalid";
    }
    int num=diffcheck1(str1, str2);
    if(num==-1){
        return "Empty";
    }
    if(str1.length()>str2.length()){
        return str1.substring(num);
    }
    else{
        return str2.substring(num);
    }

}

public static int diffcheck1(String str1,String str2)
{
    int i;
    String str;
    String strn;
    if(str1.length()>str2.length()){
        str=str1;
        strn=str2;
    }
    else{
        str=str2;
        strn=str1;
    }
    for(i=0;i<str.length() && i<strn.length();i++){
            if(str1.charAt(i)!=str2.charAt(i)){
                return i;
            }
    }
        if(i<str1.length()||i<str2.length()){
            return i;
        }

    return -1;

   }
   }

7
像这样未经测试的纯文本代码几乎没有意义。在自由开源软件(FLOSS)代码托管页面上创建一个项目,将代码和测试放在那里。 - Kalle Richter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接