Mencari Perbezaan Antara Dua Rentetan di Jawa

1. Gambaran keseluruhan

Tutorial ringkas ini akan menunjukkan cara mencari perbezaan antara dua rentetan menggunakan Java.

Untuk tutorial ini, kita akan menggunakan dua perpustakaan Java yang ada dan membandingkan pendekatan mereka terhadap masalah ini.

2. Masalahnya

Mari pertimbangkan syarat berikut: kami ingin mencari perbezaan antara rentetan " ABCDELMN" dan "ABCFGLMN".

Bergantung pada format apa yang kita mahukan outputnya, dan mengabaikan kemungkinan untuk menulis kod tersuai kami untuk melakukannya, kami menemui dua pilihan utama yang ada.

Yang pertama adalah perpustakaan yang ditulis oleh Google yang disebut diff-match-patch. Seperti yang mereka tuntut, perpustakaan menawarkan algoritma yang kuat untuk menyegerakkan teks biasa .

Pilihan lain adalah kelas StringUtils dari Apache Commons Lang.

Mari kita teliti perbezaan antara kedua-duanya.

3. perbezaan-pertandingan-tampalan

Untuk tujuan artikel ini, kami akan menggunakan garpu perpustakaan Google yang asli, kerana artifak untuk yang asli tidak dikeluarkan di Maven Central. Juga, beberapa nama kelas berbeza dari pangkalan kode asal dan lebih mematuhi piawaian Java.

Pertama, kita perlu memasukkan kebergantungannya dalam fail pom.xml kami :

 org.bitbucket.cowwoc diff-match-patch 1.2 

Kemudian, mari kita pertimbangkan kod ini:

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

Sekiranya kita menjalankan kod di atas - yang menghasilkan perbezaan antara teks1 dan teks2 - mencetak perbezaan pemboleh ubah akan menghasilkan output ini:

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

Sebenarnya, output akan menjadi senarai objek Diff , masing-masing dibentuk oleh jenis operasi ( INSERT , DELETE atau EQUAL ), dan bahagian teks yang berkaitan dengan operasi .

Semasa menjalankan perbezaan antara teks2 dan teks1, kita akan mendapat hasil ini:

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

4. StringUtils

Kelas dari Apache Commons mempunyai pendekatan yang lebih sederhana .

Pertama, kami akan menambahkan kebergantungan Apache Commons Lang ke fail pom.xml kami :

 org.apache.commons commons-lang3 3.9 

Kemudian, untuk mencari perbezaan antara dua teks dengan Apache Commons, kita akan memanggil StringUtils # Difference :

StringUtils.difference(text1, text2)

Output yang dihasilkan akan menjadi rentetan sederhana :

FGLMN

Manakala menjalankan perbezaan antara teks2 dan teks1 akan kembali:

DELMN

Pendekatan mudah ini dapat ditingkatkan dengan menggunakan StringUtils.indexOfDifference () , yang akan mengembalikan indeks di mana dua rentetan mula berbeza (dalam kes kita, watak keempat rentetan). Indeks ini dapat digunakan untuk mendapatkan substring dari rentetan asli , untuk menunjukkan apa yang umum di antara dua input , selain yang berbeza.

5. Persembahan

Untuk penanda aras kami, kami menghasilkan senarai 10,000 rentetan dengan bahagian tetap 10 aksara , diikuti oleh 20 aksara abjad rawak .

Kami kemudian mencari senarai dan melakukan perbezaan antara elemen n dan elemen n + 1 dari senarai:

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

Akhirnya, mari jalankan penanda aras dan bandingkan dua perpustakaan:

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. Kesimpulannya

Dari segi kelajuan pelaksanaan yang murni, StringUtils jelas lebih berprestasi , walaupun hanya mengembalikan substring dari mana kedua rentetan itu mulai berbeza.

Pada masa yang sama, Diff-Match-Patch memberikan hasil perbandingan yang lebih teliti , dengan mengorbankan prestasi.

Pelaksanaan contoh dan potongan ini boleh didapati di GitHub.