1. Koleksi di Java
Kelas koleksi di Java adalah kelas yang paling sering digunakan dan paling nyaman dalam pemrograman Java. Sebagai kelas kontainer, kelas pengumpulan dapat menyimpan semua jenis data, dan tentu saja juga dapat menyimpan jenis yang ditentukan dalam kombinasi dengan obat generik (tetapi obat generik hanya berlaku selama periode kompilasi dan akan dihapus saat runtime). Apa yang disimpan di kelas koleksi hanyalah referensi ke objek, bukan referensi ke objek itu sendiri. Kapasitas kelas pengumpulan dapat diperluas secara dinamis selama operasi, dan juga menyediakan banyak metode yang nyaman, seperti menemukan persatuan dan persimpangan koleksi.
2. Struktur Kelas Koleksi
Koleksi di Java mencakup beberapa struktur data, seperti daftar tertaut, antrian, tabel hash, dll. Dalam hal struktur warisan kelas, dapat dibagi menjadi dua kategori. Salah satunya diwarisi dari antarmuka koleksi. Jenis koleksi ini termasuk kelas koleksi seperti daftar, set dan antrian. Kelas lain diwarisi dari antarmuka peta, yang terutama mencakup kelas koleksi yang terkait dengan tabel hash. Mari kita lihat diagram struktur warisan dari dua kategori ini:
1. Daftar, set dan antrian
Garis putus -putus hijau pada gambar mewakili implementasi, garis solid hijau mewakili warisan antara antarmuka, dan garis padat biru mewakili pewarisan antar kelas.
(1) Daftar: Kami menggunakan lebih banyak daftar, termasuk ArrayList dan LinkedList. Perbedaan antara keduanya juga sangat jelas, yang dapat dilihat dari nama mereka. Daftar array yang mendasarinya diimplementasikan melalui array, sehingga kecepatan akses acaknya relatif cepat, tetapi efisiensinya relatif rendah untuk kasus di mana penambahan dan penghapusan yang sering diperlukan. Untuk LinkedList, lapisan yang mendasarinya diimplementasikan melalui daftar tertaut, sehingga penambahan dan operasi penghapusan lebih mudah untuk diselesaikan, tetapi efisiensi akses acak relatif rendah.
Pertama -tama mari kita lihat efisiensi penyisipan keduanya:
Paket com.paddx.test.collection; import java.util.arraylist; import java.util.linkedlist; kelas publik listTest {public static main (string [] args) {for (int i = i <; i ++) {} Long start = System.currentTimememeMemed =; i <; i ++) {} Long start = System.currentTimememememem () (i ++; LinkedList<Integer>();for(int i=;i<;i++){linkedList.add(,i);}long end = System.currentTimeMillis();System.out.println(end - start);ArrayList<Integer> arrayList = new ArrayList<Integer>();for(int i =; i <; i ++) {arraylist.add (, i);} system.out.println (System.currentTimeMillis () - end);}}Berikut adalah hasil eksekusi lokal:
dua puluh tiga
1227
Dapat dilihat bahwa dalam hal ini, efisiensi penyisipan LinkedList jauh lebih tinggi daripada arraylist, tentu saja ini adalah situasi yang relatif ekstrem. Mari kita bandingkan efisiensi akses acak antara keduanya:
package com.paddx.test.collection;import java.util.ArrayList;import java.util.LinkedList;import java.util.Random;public class ListTest {public static void main(String[] args) {Random random = new Random();for(int i=;i<;i++){}LinkedList<Integer> linkedList = new LinkedList <Integer> (); for (int i =; i <; i ++) {linkedlist.add (i);} arrayList <Integer> arrayList = ArrayList baru <Integer> (); untuk (int i =; i <; i ++) {arraylist.add (i);} start lama = system.currentTimeMillis (); untuk (int i =; i <; i ++) {int j = random.nextInt (i+); int k = linkedlist.get (j);} long end = System.currentTimeMillis (); System.out.println (end - start); untuk (int i =; i <; i ++) {int j = random.next.next); arrayList.get (j);} System.out.println (System.CurrentTimeMillis () - end);}}Inilah hasil eksekusi saya:
5277
6
Jelas bahwa efisiensi akses acak ArrayList adalah beberapa urutan besarnya lebih tinggi dari LinkedList. Melalui dua potong kode ini, kita harus dapat mengetahui lebih jelas perbedaan antara LinkedList dan ArrayList dan skenario adaptasi. Sedangkan untuk vektor, ini adalah versi arraylist yang aman dari utas, sedangkan Stack sesuai dengan struktur data stack. Keduanya lebih jarang digunakan, jadi saya tidak akan memberikan contoh di sini.
(2) Antrian: Umumnya, dapat dilakukan secara langsung menggunakan LinkedList. Ini juga dapat dilihat dari diagram kelas di atas yang diwariskan LinkedList dari Deque, sehingga LinkedList memiliki fungsi antrian ganda. PriityQueue ditandai dengan memberikan prioritas untuk setiap elemen, dan elemen dengan prioritas tinggi akan diberikan prioritas dari antrian.
(3) Set: Perbedaan utama antara set dan daftar adalah bahwa set tidak mengizinkan elemen diulang, sedangkan daftar dapat memungkinkan elemen diulang. Untuk menilai pengulangan elemen, kita perlu memutuskan berdasarkan metode hash objek dan metode yang sama. Ini juga mengapa kami biasanya mengganti metode hashcode dan sama dengan metode untuk kelas elemen dalam koleksi. Mari kita ambil contoh untuk melihat perbedaan antara set dan daftar, serta peran metode kode hash dan sama dengan metode:
Paket com.paddx.test.collection; import java.util.arraylist; import java.util.hashset; impor java.util.set; kelas publik settest {public static void main (string [] args) {person p1 = orang baru ("lxp", 10); orang p2 = orang baru ("lxp" lxp ", lxp", lxp ", 10); lxpen (" lxp ", lxp", lxp ", lxp", lxp ", lxp", lxp ", lxp", lxp ", lxp", lxp "," Person ("LXP", 20); ArrayList <Fon> List = New ArrayList <Fon> (); list.add (p1); System.out.println ("-------------"); list.add (p2); System.out.println ("----------------"); list.add (p3); list.size ()); System.out.println ("---------------"); set <sen person> set = hashset baru <fone> (); set.add (p1); System.out.println ("------------"); set.add (p2); System.out.println ("-------------"); "P2); System.out.println (" --------- "); size = "+set.size ());} class static class person {private string name; private int usia; orang publik (nama string, int usia) {this.name = name; this.age = usia;}@overridepublic boolean setara (name o) {system.out.println (" call equals (); name = "+name (ificlic (ificln (" if ("ificln (" name; ! = o.getClass ()) return false; orang orang = (orang) o; return name.equals (person.name);}@overridepublic int hashCode () {System.out.println ("Call HashCode (), usia ="+usia); usia kembali;}}} Hasil eksekusi dari kode di atas adalah sebagai berikut:
------------
------------
Ukuran daftar = 3
---- Divide Line ----
Hubungi HashCode (), usia = 10
------------
Hubungi HashCode (), usia = 10
Call Equals (); Name = LXP
------------
Hubungi HashCode (), usia = 20
Set ukuran = 2
Dari hasilnya, tidak ada operasi tambahan yang dilakukan ketika elemen ditambahkan ke daftar dan dapat diulang. Sebelum bergabung dengan set, Anda perlu menjalankan metode kode hashcode terlebih dahulu. Jika nilai yang dikembalikan sudah ada di set, Anda perlu terus menjalankan metode Equals. Jika hasil yang dikembalikan dengan metode Equals juga benar, itu membuktikan bahwa elemen sudah ada, dan elemen baru akan ditimpa oleh elemen lama. Jika nilai kode hash yang dikembalikan berbeda, Anda akan secara langsung menambahkan set. Ingat di sini bahwa untuk elemen dalam koleksi, elemen dengan nilai kode hash yang berbeda harus tidak setara, tetapi untuk elemen dengan tidak setara memiliki nilai kode hash mungkin sama.
Perbedaan antara hashset dan linkedhashset adalah bahwa yang terakhir dapat memastikan bahwa urutan elemen yang dimasukkan ke dalam set konsisten dengan urutan output. Perbedaan antara Tresset adalah bahwa jenisnya diurutkan dalam pembanding, dan secara default, itu diatur dalam urutan naik dalam urutan alami karakter.
(4) Iterable: Dari gambar ini, Anda dapat melihat bahwa kelas koleksi mewarisi dari iterable. Fungsi antarmuka ini adalah untuk menyediakan elemen traversal, yaitu semua kelas koleksi (kecuali kelas terkait peta) menyediakan fungsi traversal elemen. Iterable berisi iterator Iterator, dan kode sumbernya adalah sebagai berikut. Jika Anda terbiasa dengan mode Iterator, itu harus mudah dimengerti.
Iterator Antarmuka Publik <E> {boolean hasnext (); e next (); void remef ();}2. Peta:
Keuntungan terbesar dari pengumpulan jenis peta adalah efisiensi pencariannya relatif tinggi, dan kompleksitas waktu O (1) dapat dicapai secara ideal. Peta yang paling umum digunakan adalah hashmap. Perbedaan antara LinkedHashMap dan HashMap adalah bahwa yang pertama dapat memastikan bahwa urutan elemen yang dimasukkan ke dalam set konsisten dengan urutan output. Perbedaan antara keduanya dan TreeMap adalah bahwa TreeMap diurutkan sesuai dengan nilai -nilai kunci. Tentu saja, implementasinya yang mendasarinya juga memiliki perbedaan penting. Misalnya, lapisan hashmap yang mendasari adalah meja hash, sedangkan lapisan TreeMap yang mendasarinya adalah pohon. Sekarang mari kita lihat perbedaan antara TreeMap dan LinkedHashMap:
package com.paddx.test.collection;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;import java.util.TreeMap;public class MapTest {public static void main(String[] args) {Map<String,String> treeMap = new TreeMap<String,String>();Map<String,String> LinkedMap = new LinkedHashMap <String, String> (); treemap.put ("b", null); treemap.put ("c", null); treemap.put ("a", null); untuk (iterator <string> iter = treemap.keyset (). iterator (); iter.hasnext ();) {System.out.println ("treemap ="+iter.next ());} system.out.prin tln ("---------- 分割线 ---------"); linkedmap.put ("b", null); linkedmap.put ("c", null); linkedmap.put ("a", null); untuk (Iterator <string> iter = linkedmap.keyset (). Iterator (); iter.hasnext ();) {System.out.println ("linkedHashMap ="+iter.next ());}}} Jalankan kode di atas dan hasil eksekusi adalah sebagai berikut:
Treemap = a
Treemap = b
Treemap = c
-------------------------
LinkedHashMap = b
LinkedHashMap = c
LinkedHashMap = a
Dari hasil berjalan, jelas bahwa perbedaan antara TreeMap dan LinkedHashMap terlihat jelas. Yang pertama adalah output dengan penyortiran string, sedangkan yang terakhir adalah output dengan urutan penyisipan. Pembaca yang cermat dapat menemukan bahwa perbedaan antara HashMap dan TreeMap konsisten dengan perbedaan yang disebutkan sebelumnya antara hashset dan treeset. Saat melakukan analisis kode sumber di masa depan, kita dapat melihat bahwa hashset dan treeset pada dasarnya diimplementasikan melalui hashmap dan treemap masing -masing, sehingga perbedaannya secara alami sama. Hashtable jarang digunakan sekarang. Perbedaan utama dari hashmap adalah bahwa hashtable aman-utas, tetapi karena efisiensinya yang rendah, hashmap biasanya digunakan. Dalam lingkungan multi-threaded, CurrentHashMap biasanya digunakan sebagai gantinya.
3. Ringkasan
Artikel ini hanya memperkenalkan kerangka kerja koleksi Java dan hubungan warisannya secara keseluruhan. Selain kelas -kelas di atas, koleksi juga menyediakan dua kelas alat: koleksi dan array. Selain itu, penyortiran dalam koleksi terkait erat dengan sebanding dan komparator. Dalam artikel berikutnya, kode sumber implementasi kelas yang disebutkan di atas dalam JDK akan dianalisis secara rinci.