Prestasi removeAll () dalam HashSet

1. Gambaran keseluruhan

HashSet adalah koleksi untuk menyimpan elemen unik.

Dalam tutorial ini, kita akan membincangkan prestasi kaedah removeAll () di kelas java.util.HashSet .

2. HashSet.removeAll ()

The removeAll kaedah membuang semua unsur-unsur, yang terkandung dalam koleksi :

Set set = new HashSet(); set.add(1); set.add(2); set.add(3); set.add(4); Collection collection = new ArrayList(); collection.add(1); collection.add(3); set.removeAll(collection); Integer[] actualElements = new Integer[set.size()]; Integer[] expectedElements = new Integer[] { 2, 4 }; assertArrayEquals(expectedElements, set.toArray(actualElements)); 

Akibatnya, elemen 1 dan 3 akan dikeluarkan dari set.

3. Pelaksanaan Dalaman dan Kerumitan Masa

Kaedah removeAll () menentukan mana yang lebih kecil - set atau koleksi. Ini dilakukan dengan menggunakan kaedah size () pada set dan koleksi.

Sekiranya koleksi tersebut mempunyai unsur yang lebih sedikit daripada set , maka iterasi pada koleksi yang ditentukan dengan kerumitan masa O ( n ). Ia juga memeriksa apakah elemen tersebut terdapat dalam set dengan kerumitan waktu O (1). Dan jika elemen itu ada, ia dikeluarkan dari set menggunakan kaedah remove () dari set, yang sekali lagi mempunyai kerumitan waktu O (1). Jadi kerumitan masa keseluruhan adalah O ( n ) .

Sekiranya himpunan mempunyai elemen yang lebih sedikit daripada koleksi , maka iterasi pada set ini menggunakan O ( n ). Kemudian memeriksa apakah setiap elemen ada dalam koleksi dengan menggunakan kaedah mengandung () . Dan jika elemen seperti itu ada, maka elemen tersebut dikeluarkan dari set. Jadi ini bergantung pada kerumitan masa kaedah mengandung () .

Sekarang dalam kes ini, jika koleksi adalah ArrayList , kerumitan masa kaedah mengandung () adalah O ( m ). Jadi kerumitan masa secara keseluruhan untuk membuang semua elemen yang terdapat dalam ArrayList dari set adalah O ( n * m ) .

Sekiranya koleksi itu lagi HashSet , kerumitan masa kaedah mengandung () adalah O (1). Jadi kerumitan masa secara keseluruhan untuk membuang semua elemen yang terdapat dalam HashSet dari set adalah O ( n ) .

4. Prestasi

Untuk melihat perbezaan prestasi antara 3 kes di atas, mari tulis ujian penanda aras JMH ringkas.

Untuk kes pertama, kami akan memulakan set dan koleksi, di mana kami mempunyai lebih banyak elemen dalam set daripada koleksi. Dalam kes kedua, kami akan menginisialisasi set dan koleksi, di mana kami mempunyai lebih banyak elemen dalam koleksi daripada set. Dan dalam kes ketiga, kita akan menginisialisasi 2 set, di mana kita akan mempunyai set ke-2 yang mempunyai lebih banyak unsur daripada yang pertama:

@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 5) public class HashSetBenchmark { @State(Scope.Thread) public static class MyState { private Set employeeSet1 = new HashSet(); private List employeeList1 = new ArrayList(); private Set employeeSet2 = new HashSet(); private List employeeList2 = new ArrayList(); private Set employeeSet3 = new HashSet(); private Set employeeSet4 = new HashSet(); private long set1Size = 60000; private long list1Size = 50000; private long set2Size = 50000; private long list2Size = 60000; private long set3Size = 50000; private long set4Size = 60000; @Setup(Level.Trial) public void setUp() { // populating sets } } }

Selepas itu, kami menambah ujian penanda aras kami:

@Benchmark public boolean given_SizeOfHashsetGreaterThanSizeOfCollection_whenRemoveAllFromHashSet_thenGoodPerformance(MyState state) { return state.employeeSet1.removeAll(state.employeeList1); } @Benchmark public boolean given_SizeOfHashsetSmallerThanSizeOfCollection_whenRemoveAllFromHashSet_thenBadPerformance(MyState state) { return state.employeeSet2.removeAll(state.employeeList2); } @Benchmark public boolean given_SizeOfHashsetSmallerThanSizeOfAnotherHashSet_whenRemoveAllFromHashSet_thenGoodPerformance(MyState state) { return state.employeeSet3.removeAll(state.employeeSet4); }

Dan inilah hasilnya:

Benchmark Mode Cnt Score Error Units HashSetBenchmark.testHashSetSizeGreaterThanCollection avgt 20 2700457.099 ± 475673.379 ns/op HashSetBenchmark.testHashSetSmallerThanCollection avgt 20 31522676649.950 ± 3556834894.168 ns/op HashSetBenchmark.testHashSetSmallerThanOtherHashset avgt 20 2672757.784 ± 224505.866 ns/op

Kita dapat melihat HashSet.removeAll () berprestasi sangat buruk apabila HashSet mempunyai elemen yang lebih sedikit daripada Koleksi , yang diteruskan sebagai argumen kepada kaedah removeAll () . Tetapi apabila koleksi lain adalah HashSet , maka prestasinya bagus.

5. Kesimpulan

Dalam artikel ini, kami melihat prestasi removeAll () di HashSet. Apabila himpunan mempunyai elemen yang lebih sedikit daripada koleksi, maka prestasi removeAll () bergantung pada kerumitan waktu kaedah berisi () koleksi.

Seperti biasa, kod lengkap untuk artikel ini terdapat di GitHub.