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 strings“ABCDELMN ”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.