Как выполнить строковые различия в Java?

Мне нужно выполнить различия между строками Java. Я хотел бы иметь возможность перестроить строку, используя исходную версию строки и diff. Кто-нибудь делал это на Яве? Какую библиотеку вы используете?

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

Также см. stackoverflow.com/questions/479654/…

Stewart 17.06.2013 20:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
53
1
76 981
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Apache Commons имеет String diff

org.apache.commons.lang.StringUtils

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

Он возвращает остаток от второй строки, начиная с того места, где она отличается от первой. Для меня это недостаточно эффективно, так как я буду работать с большими текстами. См .: StringUtils.difference («ab», «abxyz») -> «xyz» StringUtils.difference («ab», «xyzab») -> «xyzab»;

Sergio del Amo 25.09.2008 14:33

Также остерегайтесь этой ошибки: StringUtils.difference("abc", "") = ""StringUtils.difference("abc", "abc") = ""

Alec 04.07.2016 20:57

Используйте Расстояние Левенштейна и извлеките журналы редактирования из матрицы, которую создает алгоритм. В статье в Википедии есть ссылки на несколько реализаций, я уверен, что среди них есть реализация Java.

Левенштейн - это частный случай алгоритма Самая длинная общая подпоследовательность, вы также можете взглянуть на него.

Ответ принят как подходящий

Кажется, эта библиотека помогает: Google-diff-match-patch. Он может создать строку патча из различий и позволить повторно применить патч.

редактировать: Другим решением может быть https://code.google.com/p/java-diff-utils/

Это разные библиотеки, FWIW

Kerinin 11.06.2013 02:00

Репозиторий Maven для google-diff-match-patch - там.

fracz 15.01.2016 00:14

Активно поддерживаемый форк java-diff-utils выглядит как github.com/bkromhout/java-diff-utils

koppor 23.11.2016 09:55

google-diff-match-patch на github: github.com/GerHobbelt/google-diff-match-patch

isapir 03.07.2017 19:41

Поддерживаемая вилка, похоже, теперь github.com/java-diff-utils/java-diff-utils

golimar 03.02.2021 13:48

Как говорит Торстен, вы можете использовать

org.apache.commons.lang.StringUtils;

System.err.println(StringUtils.getLevenshteinDistance("foobar", "bar"));

Спасибо, но getLevenshteinDistance просто возвращает целое число. Этого недостаточно, чтобы восстановить струны.

Hans-Peter Störr 21.09.2015 17:04

@hstoerr, вы правы, я, должно быть, пропустил эту часть в исходном вопросе. Давным-давно :)

Paul Whelan 22.09.2015 15:04

Этот метод также устарел.

Constantino Cronemberger 05.08.2019 15:27

Если вам нужно иметь дело с различиями между большими объемами данных и эффективно сжать различия, вы можете попробовать Java-реализацию xdelta, которая, в свою очередь, реализует RFC 3284 (VCDIFF) для двоичных различий (также должна работать со строками).

Может пригодиться библиотека Различия в Java.

Репозиторий github.com/bkromhout/java-diff-utils был создан косвенно из исходного репозитория GitHub и лучше поддерживается. Может, там можно объединить силы?

koppor 24.11.2016 11:19

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;

   }
   }

Такой непроверенный текстовый код почти никогда не имеет смысла. Создайте проект на странице хостинга кода FLOSS и разместите там код + тесты.

Karl Richter 21.06.2017 21:00

Текст Apache Commons теперь имеет 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);
    }
});

Другие вопросы по теме