Descobrindo a diferença entre duas strings em Java

Descobrindo a diferença entre duas strings em Java

1. Visão geral

Este tutorial rápido mostrará comofind the difference between two strings usando Java.

Para este tutorial, vamos usartwo existing Java librariese comparar suas abordagens para este problema.

2. O problema

Vamos considerar o seguinte requisito: queremos encontrar a diferença entre as stringsABCDELMN ”e“ ABCFGLMN ”.

Dependendo do formato em que precisamos que a saída seja, e ignorando a possibilidade de escrever nosso código personalizado, encontramos duas opções principais disponíveis.

O primeiro é uma biblioteca escrita pelo Google chamadadiff-match-patch. Como eles afirmam, a biblioteca oferecerobust algorithms for synchronizing plain text.

A outra opção é oStringUtils class do Apache Commons Lang.

Vamos explorar as diferenças entre esses dois.

3. diff-match-patch

Para o propósito deste artigo, usaremosa fork of the original Google library, pois os artefatos do original não foram liberados no Maven Central. Além disso, alguns nomes de classe são diferentes da base de código original e são mais aderentes aos padrões Java.

Primeiro, precisaremos incluir sua dependência em nossopom.xml file:


    org.bitbucket.cowwoc
    diff-match-patch
    1.2

Então, vamos considerar este código:

String text1 = "ABCDELMN";
String text2 = "ABCFGLMN";
DiffMatchPatch dmp = new DiffMatchPatch();
LinkedList diff = dmp.diffMain(text1, text2, false);

Se executarmos o código acima - que produz a diferença entretext1 etext2 - imprimir a variáveldiff produzirá esta saída:

[Diff(EQUAL,"ABC"), Diff(DELETE,"DE"), Diff(INSERT,"FG"), Diff(EQUAL,"LMN")]

Na verdade, a saída será alist of Diff objects, cada um sendoformed by an operation type (INSERT,DELETE ouEQUAL) ethe portion of text associated with the operation.

Ao executar o diff entretext2 etext1,, obteremos este resultado:

[Diff(EQUAL,"ABC"), Diff(DELETE,"FG"), Diff(INSERT,"DE"), Diff(EQUAL,"LMN")]

4. StringUtils

A classe deApache Commons tem ummore simplistic approach.

Primeiro, vamos adicionarthe Apache Commons Lang dependency ao nossopom.xml file:


    org.apache.commons
    commons-lang3
    3.9

Então, para encontrar a diferença entre dois textos com Apache Commons, chamaríamosStringUtils#Difference:

StringUtils.difference(text1, text2)

A saída produziuwill be a simple string:

FGLMN

Ao passo que executar a diferença entretext2 etext1 retornará:

DELMN

Esta abordagem simplescan be enhanced usingStringUtils.indexOfDifference(), quewill return theindex at which the two strings start to differ (no nosso caso, o quarto caractere da string). Este índice pode ser usado paraget a substring of the original string, para mostrarwhat is common between the two inputs, além do que é diferente.

5. atuação

Para nossos benchmarks, geramos uma lista de 10.000 strings coma fixed portion of 10 characters, seguido por20 random alphabetic characters.

Em seguida, percorremos a lista e fazemos uma comparação entre o elementonth e o elementon+1th da lista:

@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();
}

Finalmente, vamos executar os benchmarks e comparar as duas bibliotecas:

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

6. Conclusão

Em termos de velocidade de execução pura,StringUtils is clearly more performant, embora só retorne a substring a partir da qual as duas strings começam a diferir.

Ao mesmo tempo,Diff-Match-Patch fornece ummore thorough comparison result, em detrimento do desempenho.

A implementação desses exemplos e snippets está disponívelover on GitHub.