1. 개요

이 빠른 예제은 Java를 사용하여 두 문자열의 차이점찾는 방법을 보여줍니다 .

이 예제에서는 두 개의 기존 Java 라이브러리 를 사용 하고이 문제에 대한 접근 방식을 비교할 것입니다.

2. 문제

다음 요구 사항을 고려해 보겠습니다. 문자열 " ABCDELMN"과 "ABCFGLMN" 간의 차이를 찾고 싶습니다 .

출력이 필요한 형식에 따라 사용자 지정 코드를 작성할 가능성을 무시하고 두 가지 주요 옵션을 사용할 수 있습니다.

첫 번째는 diff-match-patch 라는 Google에서 작성한 라이브러리입니다  . 그들이 주장했듯이 라이브러리는 일반 텍스트 동기화를위한 강력한 알고리즘을 제공 합니다 .

다른 옵션은 Apache Commons Lang StringUtils  클래스입니다.

이 둘의 차이점을 살펴 보겠습니다.

3. diff-match-patch

이 기사의 목적을 위해 원래 Google 라이브러리의 포크를 사용합니다. 원래 라이브러리 의 아티팩트는 Maven Central에서 릴리스되지 않기 때문입니다. 또한 일부 클래스 이름은 원래 코드베이스와 다르며 Java 표준을 더 잘 준수합니다.

먼저 pom.xml  파일에 의존성을 포함해야 합니다.

<dependency>
    <groupId>org.bitbucket.cowwoc</groupId>
    <artifactId>diff-match-patch</artifactId>
    <version>1.2</version>
</dependency>

그런 다음이 코드를 살펴 보겠습니다.

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

위의 코드를 실행하면 -text1text2 의 차이를 생성합니다 -변수 diff인쇄하면 다음 같은 출력이 생성됩니다.

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

실제로 출력은 Diff 객체List이며 , 각각 은 작업 유형 ( INSERT , DELETE 또는 EQUAL ) 및 작업과 관련된 텍스트 부분으로 구성됩니다 .

text2text1 사이의 diff를 실행하면 다음 같은 결과를 얻을 수 있습니다.

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

4. StringUtils

Apache Commons 의 클래스 보다 단순한 접근 방식을 사용 합니다.

먼저 pom.xml  파일에 Apache Commons Lang 의존성추가 합니다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.11</version>
</dependency>

그런 다음 Apache Commons를 사용하여 두 텍스트의 차이점을 찾기 위해 StringUtils # Difference를 호출합니다 .

StringUtils.difference(text1, text2)

생성 된 출력 은 간단한 문자열입니다 .

FGLMN

text2text1 사이의 diff를 실행하면 다음이 반환됩니다.

DELMN

이 간단한 방식은 사용을 향상시킬 수있다 StringUtils.indexOfDifference () , 리턴한다 두 문자열이 다른 시작되는 인덱스 (우리의 경우 문자열의 문자를 제). 이 인덱스는 원래 문자열의 하위 문자열가져 와서 두 입력 간의 공통점과 차이점 을 표시 하는 데 사용할 수 있습니다 .

5. 성능

벤치 마크를 위해 고정 된 부분이 10 자 이고 그 뒤에 20 개의 랜덤의 알파벳 문자있는 10,000 개의 문자열 List을 생성합니다 .

그런 다음 List을 반복하고 List의 n 번째 요소와 n + 1 번째 요소 사이에 diff를 수행 합니다.

@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

6. 결론

순수한 실행 속도 측면에서 StringUtils 두 문자열이 다른 부분 문자열 만 반환하지만 분명히 더 성능이 뛰어납니다 .

동시에 Diff-Match-Patch성능을 희생하면서 보다 철저한 비교 결과를 제공합니다 .

이러한 예제 및 스 니펫의 구현은 GitHub에서 사용할 수 있습니다 .