Saya mencoba untuk mengoptimalkan sepotong kode yang membandingkan elemen daftar.
Misalnya.
public void compare(Set<Record> firstSet, Set<Record> secondSet){
for(Record firstRecord : firstSet){
for(Record secondRecord : secondSet){
// comparing logic
}
}
}
Harap diperhatikan bahwa jumlah record dalam set akan tinggi.
Terima kasih
Shekhar
java
performance
set
Shekhar
sumber
sumber
Jawaban:
Ini benar-benar tergantung pada apa yang ingin Anda lakukan dalam logika perbandingan ... yaitu apa yang terjadi jika Anda menemukan elemen dalam satu himpunan bukan di himpunan lainnya? Metode Anda memiliki
void
tipe pengembalian jadi saya berasumsi Anda akan melakukan pekerjaan yang diperlukan dalam metode ini.Kontrol yang lebih halus jika Anda membutuhkannya:
Jika Anda perlu mendapatkan elemen yang ada di satu set dan bukan yang lain.
EDIT:
set.removeAll(otherSet)
mengembalikan boolean, bukan satu set. Untuk menggunakan removeAll (), Anda harus menyalin set lalu menggunakannya.Jika isi
one
dantwo
keduanya kosong, maka Anda tahu bahwa kedua himpunan itu sama. Jika tidak, maka Anda memiliki elemen yang membuat himpunan tidak sama.Anda menyebutkan bahwa jumlah record mungkin tinggi. Jika implementasi yang mendasarinya adalah,
HashSet
maka pengambilan setiap record dilakukanO(1)
tepat waktu, jadi Anda tidak bisa mendapatkan yang lebih baik dari itu.TreeSet
adalahO(log n)
.sumber
equals
lebih cepat dari dua panggilan kecontainsAll
dalam kasus terburuk; lihat jawabanku.Jika Anda hanya ingin mengetahui apakah setnya sama,
equals
metode onAbstractSet
diimplementasikan secara kasar seperti di bawah ini:Perhatikan bagaimana ini mengoptimalkan kasus umum di mana:
Setelah itu,
containsAll(...)
akan kembalifalse
segera setelah menemukan elemen di himpunan lain yang juga tidak ada di himpunan ini. Tetapi jika semua elemen ada di kedua set, itu perlu menguji semuanya.Oleh karena itu, kinerja kasus terburuk terjadi ketika dua set objek yang sama tetapi tidak sama. Biaya tersebut biasanya
O(N)
atauO(NlogN)
tergantung pada penerapannyathis.containsAll(c)
.Dan Anda akan mendapatkan kinerja kasus yang mendekati terburuk jika setnya besar dan hanya berbeda dalam persentase kecil elemen.
MEMPERBARUI
Jika Anda ingin menginvestasikan waktu dalam implementasi kumpulan kustom, ada pendekatan yang dapat meningkatkan kasus "hampir sama".
Idenya adalah Anda perlu menghitung sebelumnya dan menyimpan hash ke cache untuk seluruh set sehingga Anda bisa mendapatkan nilai kode hash set saat ini
O(1)
. Kemudian Anda dapat membandingkan kode hash untuk dua set sebagai percepatan.Bagaimana Anda bisa menerapkan kode hash seperti itu? Nah jika set hashcode-nya adalah:
maka Anda dapat dengan murah memperbarui kode hash cache set setiap kali Anda menambahkan atau menghapus elemen. Dalam kedua kasus, Anda cukup melakukan XOR kode hash elemen dengan kode hash set saat ini.
Tentu saja, ini mengasumsikan bahwa kode hash elemen stabil sementara elemen adalah anggota set. Ini juga mengasumsikan bahwa fungsi kode hash kelas elemen memberikan penyebaran yang baik. Itu karena ketika dua set kode hash sama, Anda masih harus kembali ke
O(N)
perbandingan semua elemen.Anda dapat mengambil ide ini lebih jauh ... setidaknya dalam teori.
PERINGATAN - Ini sangat spekulatif. Sebuah "eksperimen pikiran" jika Anda suka.
Misalkan kelas elemen set Anda memiliki metode untuk mengembalikan checksum crypto untuk elemen tersebut. Sekarang implementasikan checksum set dengan XOR checksum yang dikembalikan untuk elemen.
Apa yang dibeli ini untuk kita?
Nah, jika kita berasumsi bahwa tidak ada kesalahan yang terjadi, probabilitas bahwa dua elemen himpunan yang tidak sama memiliki checksum N-bit yang sama adalah 2 -N . Dan probabilitas 2 himpunan tidak sama memiliki checksum N-bit yang sama juga 2 -N . Jadi ide saya adalah Anda dapat menerapkan
equals
sebagai:Berdasarkan asumsi di atas, ini hanya akan memberi Anda jawaban yang salah sekali dalam waktu 2 -N . Jika Anda membuat N cukup besar (misalnya 512 bit), kemungkinan jawaban yang salah dapat diabaikan (misalnya kira-kira 10 -150 ).
Kelemahannya adalah bahwa menghitung checksum kripto untuk elemen sangat mahal, terutama karena jumlah bit meningkat. Jadi, Anda benar-benar membutuhkan mekanisme yang efektif untuk membuat memo checksum. Dan itu bisa menjadi masalah.
Dan sisi negatif lainnya adalah bahwa probabilitas kesalahan yang bukan nol mungkin tidak dapat diterima tidak peduli seberapa kecil probabilitasnya. (Tetapi jika itu masalahnya ... bagaimana Anda menangani kasus di mana sinar kosmik membalik sedikit kritis? Atau jika secara bersamaan membalik bit yang sama dalam dua contoh sistem redundan?)
sumber
Ada metode dalam Jambu
Sets
yang dapat membantu di sini:sumber
Anda memiliki solusi berikut dari https://www.mkyong.com/java/java-how-to-compare-two-sets/
Atau jika Anda lebih suka menggunakan pernyataan pengembalian tunggal:
sumber
equals()
metode dariAbstractSet
(dikirim dengan JDK) yang hampir sama dengan solusi di sini kecuali untuk pemeriksaan null tambahan . Antarmuka Set Java-11Ada solusi O (N) untuk kasus yang sangat spesifik di mana:
Kode berikut mengasumsikan bahwa kedua set didasarkan pada catatan yang sebanding. Metode serupa dapat didasarkan pada Comparator.
sumber
Jika Anda menggunakan
Guava
perpustakaan, itu mungkin untuk dilakukan:Dan kemudian buat kesimpulan berdasarkan ini.
sumber
Saya akan meletakkan secondSet di HashMap sebelum perbandingan. Dengan cara ini Anda akan mengurangi waktu pencarian daftar kedua menjadi n (1). Seperti ini:
sumber
sumber
Saya pikir referensi metode dengan metode yang sama dapat digunakan. Kami berasumsi bahwa tipe objek tanpa bayangan keraguan memiliki metode perbandingannya sendiri. Contoh yang jelas dan sederhana ada di sini,
sumber
set.equals(set2)