Ada beberapa perbedaan antara HashMap
dan Hashtable
di Jawa:
Hashtable
adalah disinkronkan, sedangkan HashMap
tidak. Hal ini membuat HashMap
baik untuk non-threaded aplikasi, seperti unsynchronized benda-Benda yang biasanya melakukan lebih baik daripada yang disinkronkan.
Hashtable
tidak memungkinkan null
tombol atau nilai-nilai. HashMap
memungkinkan null
kunci dan sejumlah null
nilai-nilai.
Salah satu dari HashMap's subclass adalah LinkedHashMap
, jadi dalam hal bahwa anda'd inginkan diprediksi iterasi order (yang penyisipan order by default), anda bisa dengan mudah menukar HashMap
untuk LinkedHashMap
. Ini tidak't menjadi mudah jika anda menggunakan Hashtable
.
Sejak sinkronisasi ini tidak menjadi masalah bagi anda, saya'd merekomendasikan HashMap
. Jika sinkronisasi menjadi masalah, anda mungkin juga melihat ConcurrentHashMap
.
Catatan, bahwa banyak jawaban yang menyatakan bahwa Hashtable disinkronkan. Dalam praktek ini membeli anda sangat sedikit. Sinkronisasi pada accessor / mutator methods akan berhenti dua benang menambahkan atau menghapus dari peta secara bersamaan, tapi di dunia nyata anda akan sering perlu tambahan sinkronisasi.
Yang sangat umum idiom adalah untuk "periksa kemudian dimasukkan" — yaitu mencari entri dalam Peta
, dan tambahkan jika tidak sudah ada. Hal ini tidak dengan cara apapun atom operasi apakah anda menggunakan Hashtable
atau HashMap
.
Sbdk diselaraskan HashMap
dapat diperoleh dengan:
Collections.synchronizedMap(myMap);
Tapi untuk benar menerapkan logika ini anda perlu tambahan sinkronisasi bentuk:
synchronized(myMap) {
if (!myMap.containsKey("tomato"))
myMap.put("tomato", "red");
}
Bahkan iterasi yang Hashtable
's file (atau HashMap
diperoleh Koleksi.synchronizedMap
) adalah tidak thread safe, kecuali jika anda juga menjaga Peta
dari yang dimodifikasi melalui tambahan sinkronisasi.
Implementasi dari ConcurrentMap
interface (misalnya ConcurrentHashMap
) memecahkan beberapa ini termasuk thread brankas, check-kemudian-undang semantik seperti:
ConcurrentMap.putIfAbsent(key, value);
Hashtable
dianggap warisan kode. Ada's apa-apa tentang Hashtable
yang dapat't dapat dilakukan dengan menggunakan HashMap
atau derivasi dari HashMap
, jadi untuk kode baru, I don't melihat alasan apa pun untuk kembali ke Hashtable
.
Pertanyaan ini sering diajukan dalam wawancara untuk memeriksa apakah calon memahami penggunaan yang benar dari kelas koleksi dan menyadari alternatif solusi yang tersedia.
Catatan pada Beberapa Istilah Penting
HashMap dapat disinkronkan dengan
Peta m = Koleksi.synchronizeMap(hashMap);
Peta ini menyediakan Koleksi views bukan dukungan langsung untuk iterasi melalui Pendataan objek. Koleksi pemandangan yang sangat meningkatkan ekspresi antarmuka, seperti yang dibahas kemudian dalam bagian ini. Peta memungkinkan anda untuk iterate atas tombol, nilai-nilai, atau pasangan kunci-nilai; Hashtable tidak memberikan opsi ketiga. Peta ini menyediakan cara yang aman untuk menghapus entri di tengah-tengah iterasi; Hashtable tidak. Akhirnya, Peta perbaikan minor kekurangan dalam Hashtable antarmuka. Hashtable memiliki sebuah metode yang disebut berisi, yang mengembalikan true jika Hashtable berisi nilai yang diberikan. Diberikan nama, anda'd harapkan ini metode untuk mengembalikan true jika Hashtable yang terkandung kunci yang diberikan, karena kunci utamanya adalah akses mekanisme untuk Hashtable. Peta antarmuka ini menghilangkan sumber dari kebingungan dengan nama metode containsValue. Juga, hal ini meningkatkan antarmuka's konsistensi — containsValue parallels containsKey.
HashMap
: Sebuah implementasi dari Peta
antarmuka yang menggunakan kode hash untuk index array.
Hashtable
: Hi, 1998 disebut. Mereka ingin koleksi mereka API kembali.
Serius meskipun, anda're lebih baik tinggal jauh dari Hashtable
sama sekali. Untuk single-threaded aplikasi, anda don't perlu tambahan biaya overhead sinkronisasi. Untuk yang sangat bersamaan apps, paranoid sinkronisasi mungkin menyebabkan kelaparan, deadlock, atau tidak perlu pengumpulan sampah jeda. Seperti Tim Howland menunjuk keluar, anda mungkin menggunakan ConcurrentHashMap
sebagai gantinya.
Perlu diingat bahwa HashTable
adalah warisan kelas sebelum Java Collections Framework (JCF) diperkenalkan dan kemudian dipasang untuk melaksanakan Peta
antarmuka. Jadi adalah Vektor
dan Stack
.
Oleh karena itu, selalu menjauh dari mereka di kode baru karena selalu ada alternatif yang lebih baik di JCF sebagai orang lain telah menunjukkan.
Berikut ini adalah Jawa koleksi cheat sheet yang anda akan menemukan berguna. Perhatikan blok abu-abu berisi warisan kelas HashTable,Vektor dan Stack.
Ada banyak jawaban yang baik yang sudah diposting. I'm menambahkan beberapa poin baru dan meringkas.
HashMap
dan Hashtable
keduanya digunakan untuk menyimpan data di kunci dan nilai bentuk. Keduanya sama-sama menggunakan teknik hashing untuk menyimpan kunci unik.
Tapi ada banyak perbedaan antara HashMap dan Hashtable kelas yang diberikan di bawah ini.
HashMap
HashMap
non disinkronkan. Tidak-benang yang aman dan dapat't akan dibagi antara banyak benang yang tepat tanpa kode sinkronisasi. HashMap
memungkinkan seseorang null key dan beberapa nilai-nilai null. HashMap
adalah kelas baru diperkenalkan di JDK 1.2. HashMap
lebih cepat. HashMap
sebagai disinkronkan dengan memanggil kode ini
Peta m = Koleksi.synchronizedMap(HashMap);
HashMap
dilalui oleh Iterator. HashMap
adalah gagal-cepat. HashMap
mewarisi AbstractMap kelas. Hashtable
Hashtable
disinkronkan. Ini adalah thread-safe dan bisa dibagi dengan banyak benang. Hashtable
doesn't membiarkan null key atau nilai. Hashtable
adalah warisan kelas. Hashtable
lebih lambat. Hashtable
secara internal disinkronkan dan dapat't menjadi tidak sinkron. Hashtable
dilalui oleh Enumerator dan Iterator. Hashtable
tidak gagal-cepat. Hashtable
mewarisi Kamus kelas.Lanjut membaca Apa perbedaan antara HashMap dan Hashtable Java?
Hashtable
mirip dengan HashMap
dan memiliki antarmuka yang sama. Dianjurkan bahwa anda menggunakan HashMap
, kecuali jika anda memerlukan dukungan untuk aplikasi warisan atau anda perlu sinkronisasi, sebagai Hashtables
metode diselaraskan. Jadi dalam kasus anda seperti anda tidak multi-threading, HashMaps
adalah taruhan terbaik anda.
Di samping semua aspek-aspek penting lainnya yang telah disebutkan di sini, Koleksi API (misalnya Peta interface) yang dimodifikasi sepanjang waktu untuk menyesuaikan diri dengan "terbaru dan terbesar" penambahan Jawa spec.
Misalnya, membandingkan Jawa 5 Peta iterasi:
for (Elem elem : map.keys()) {
elem.doSth();
}
terhadap lama Hashtable pendekatan:
for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
Elem elem = (Elem) en.nextElement();
elem.doSth();
}
Di Jawa 1.8 kami juga berjanji untuk dapat membangun dan akses HashMaps seperti di baik tua bahasa scripting:
Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];
Update: Tidak, mereka tidak't tanah di 1.8... :(
Perbedaan utama antara hashtable dan hashmap adalah bahwa Iterator dalam HashMap adalah gagal-cepat sementara enumerator untuk Hashtable tidak dan membuang ConcurrentModificationException jika ada Thread lain memodifikasi peta secara struktural dengan menambahkan atau menghapus setiap elemen kecuali Iterator's sendiri hapus() metode. Tapi ini tidak dijamin perilaku dan akan dilakukan oleh JVM pada upaya terbaik."
Sumber saya: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html
HashMap
dan Hashtable
memiliki signifikan algoritmik perbedaan juga. Tidak ada yang telah disebutkan sebelum ini sehingga's mengapa saya membawa itu. HashMap
akan membangun sebuah hash table dengan kekuatan dua ukuran, peningkatan itu dinamis seperti yang anda miliki di paling sekitar delapan elemen (tabrakan) dalam ember dan akan membangkitkan unsur-unsur yang sangat baik untuk umum jenis elemen. Namun, Hashtable
implementasi yang lebih baik dan kontrol yang lebih hashing jika anda tahu apa yang anda lakukan, yaitu anda dapat memperbaiki ukuran meja menggunakan misalnya terdekat perdana nomor ke nilai domain size dan hal ini akan mengakibatkan kinerja yang lebih baik dari HashMap yaitu kurang tabrakan untuk beberapa kasus.
Terpisah dari perbedaan yang jelas dibahas secara luas dalam pertanyaan ini, saya melihat Hashtable sebagai "manual drive" mobil di mana anda memiliki kontrol yang lebih baik atas hashing dan HashMap sebagai "otomatis drive" mitra yang umumnya akan melakukan dengan baik.
Peta m = Koleksi.synchronizedMap(new HashMap(...));
HashTable hanya dapat berisi non-null object sebagai kunci atau sebagai nilai. HashMap dapat berisi satu null kunci dan nilai-nilai null.
Iterator yang dikembalikan oleh Peta yang gagal-cepat, jika peta struktural dimodifikasi setiap saat setelah iterator dibuat, dengan cara apapun kecuali melalui iterator's sendiri menghapus metode, iterator akan membuang ConcurrentModificationException
. Dengan demikian, dalam menghadapi bersamaan modifikasi, iterator gagal dengan cepat dan bersih, daripada mempertaruhkan sewenang-wenang, non-deterministik perilaku pada waktu yang ditentukan di masa depan. Sedangkan para Mantri kembali oleh Hashtable's kunci dan elemen-elemen metode yang tidak gagal-cepat.
HashTable dan HashMap adalah anggota dari Java Collections Framework (sejak Java 2 platform v1.2, HashTable dipasang untuk melaksanakan Peta interface).
HashTable dianggap warisan kode, dokumentasi menyarankan untuk menggunakan ConcurrentHashMap di tempat Hashtable jika benang-sangat aman-bersamaan implementasi yang diinginkan.
HashMap doesn't menjamin urutan di mana unsur-unsur yang dikembalikan. Untuk HashTable saya kira itu's sama tapi aku'm tidak sepenuhnya yakin, saya don't menemukan ressource yang dengan jelas menyatakan bahwa.
Berdasarkan info di sini, I'd sarankan pergi dengan HashMap. Saya pikir keuntungan terbesar adalah bahwa pulau Jawa akan mencegah anda dari mengubah itu saat anda iterasi lebih dari itu, kecuali jika anda melakukannya melalui iterator.
Koleksi
— kadang-kadang disebut kontainer — hanya sebuah objek yang memiliki beberapa elemen menjadi satu kesatuan. Koleksi `yang digunakan untuk menyimpan, mengambil, memanipulasi, dan mengkomunikasikan data agregat. Sebuah koleksi framework W adalah suatu kesatuan arsitektur untuk merepresentasikan dan memanipulasi koleksi.
The HashMap
JDK1.2
dan Hashtable JDK1.0
, baik yang digunakan untuk mewakili sekelompok objek yang diwakili dalam <Kunci, Nilai>
pasangan. Masing-masing <Kunci, Nilai>
pasangan ini disebut Masuk
objek. Koleksi Entri ini disebut dengan objek HashMap
dan Hashtable
. Kunci dalam koleksi harus unik atau khas. [seperti mereka digunakan untuk mengambil dipetakan nilai kunci tertentu. nilai-nilai dalam koleksi dapat digandakan.] « Superclass, Warisan dan Koleksi Kerangka anggota
Hashtable adalah warisan kelas diperkenalkan di JDK1.0
, yang merupakan subclass dari Kamus kelas. Dari JDK1.2
Hashtable adalah re-engineered untuk melaksanakan Peta antarmuka untuk membuat anggota collection framework. HashMap merupakan anggota dari Java Collection Framework yang tepat dari awal diperkenalkan di JDK1.2
. HashMap merupakan subclass dari AbstractMap kelas.
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
« kapasitas Awal dan Load factor
Kapasitas adalah jumlah ember dalam tabel hash, dan kapasitas awal hanya kapasitas pada saat hash table dibuat. Perhatikan bahwa tabel hash terbuka: dalam kasus "hash
tabrakan
", satu ember menyimpan beberapa entri, yang harus dicari secara berurutan. Load factor adalah ukuran dari seberapa lengkap tabel hash diperbolehkan untuk mendapatkan sebelum kapasitasnya meningkat secara otomatis.
HashMap konstruksi kosong hash table dengan default kapasitas awal (16) dan default load factor (0.75). Di mana sebagai Hashtable konstruksi kosong hashtable dengan default kapasitas awal (11) dan load factor/mengisi rasio (0.75).
« modifikasi Struktural dalam kasus hash collision
_HashMap
, Hashtable
dalam kasus hash collisions mereka menyimpan peta entri dalam daftar terkait. Dari Java8 untuk HashMap
jika hash ember tumbuh melampaui ambang batas tertentu, ember itu akan beralih dari linked list dari file yang seimbang pohon
. yang meningkatkan terburuk kinerja dari O(n) O(log n). Sementara mengkonversi daftar ke pohon biner, kode hash digunakan sebagai percabangan variabel. Jika ada dua yang berbeda hashcodes dalam ember yang sama, yang satu dianggap lebih besar dan masuk ke kanan dari pohon dan satu ke kiri. Tapi ketika kedua hashcodes yang sama, HashMap
mengasumsikan bahwa tombol yang sebanding, dan membandingkan kunci untuk menentukan arah sehingga beberapa perintah dapat dipertahankan. Ini adalah praktik yang baik untuk membuat kunci HashMap
sebanding. Menambahkan entri jika ukuran bucket mencapai TREEIFY_THRESHOLD = 8
mengkonversi terkait daftar entri yang seimbang pohon, menghapus entri kurang dari TREEIFY_THRESHOLD
dan paling UNTREEIFY_THRESHOLD = 6
akan reconvert seimbang pohon untuk linked list entri. Jawa 8 SRC, stackpost_
« Koleksi-lihat iterasi, Gagal, dan Gagal-Aman
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
Iterator
adalah gagal-cepat di alam. aku.e melempar ConcurrentModificationException jika koleksi yang dimodifikasi saat iterasi lain dari itu sendiri hapus() metode. Di mana sebagai Penghitungan
adalah gagal-aman di alam. Tidak membuang apapun pengecualian jika koleksi yang dimodifikasi saat iterasi.
Menurut Java API Docs, Iterator adalah selalu lebih disukai Pencacahan.
CATATAN: fungsi dari Pencacahan antarmuka diduplikasi oleh interface Iterator. Selain itu, Iterator menambahkan opsional menghapus operasi, dan memiliki lebih pendek nama metode. Implementasi baru harus mempertimbangkan menggunakan Iterator dalam preferensi untuk Pencacahan.
Di Jawa 5 diperkenalkan ConcurrentMap Interface: ConcurrentHashMap
- yang sangat bersamaan, kinerja tinggi ConcurrentMap
implementasi yang didukung oleh sebuah tabel hash. Implementasi ini tidak pernah blok ketika melakukan retrievals dan memungkinkan klien untuk memilih concurrency tingkat untuk update. Hal ini dimaksudkan sebagai pengganti drop-in untuk Hashtable
: selain menerapkan ConcurrentMap
, mendukung semua "warisan" metode aneh untuk Hashtable
.
Masing-masing `HashMapEntry nilai stabil sehingga membuat butiran halus konsistensi untuk berpendapat modifikasi dan selanjutnya berbunyi; setiap baca mencerminkan paling baru selesai update
Iterator dan Mantri yang Gagal Aman - mencerminkan keadaan di beberapa titik sejak penciptaan iterator/pencacahan; hal ini memungkinkan untuk secara simultan membaca dan modifikasi pada biaya dikurangi konsistensi. Mereka tidak membuang ConcurrentModificationException. Namun, iterator yang dirancang untuk digunakan oleh hanya satu thread pada suatu waktu.
Like Hashtable
tapi tidak seperti HashMap
, kelas ini tidak memungkinkan null yang akan digunakan sebagai kunci atau nilai.
public static void main(String[] args) {
//HashMap<String, Integer> hash = new HashMap<String, Integer>();
Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
//ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
new Thread() {
@Override public void run() {
try {
for (int i = 10; i < 20; i++) {
sleepThread(1);
System.out.println("T1 :- Key"+i);
hash.put("Key"+i, i);
}
System.out.println( System.identityHashCode( hash ) );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override public void run() {
try {
sleepThread(5);
// ConcurrentHashMap traverse using Iterator, Enumeration is Fail-Safe.
// Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
sleepThread(1);
System.out.println("T2 : "+ e.nextElement());
}
// HashMap traverse using Iterator, Enumeration is Fail-Fast.
/*
for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
sleepThread(1);
System.out.println("T2 : "+ it.next());
// ConcurrentModificationException at java.util.Hashtable$Enumerator.next
}
*/
/*
Set< Entry<String, Integer> > entrySet = hash.entrySet();
Iterator< Entry<String, Integer> > it = entrySet.iterator();
Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
while( entryEnumeration.hasMoreElements() ) {
sleepThread(1);
Entry<String, Integer> nextElement = entryEnumeration.nextElement();
System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
//java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
// at java.util.HashMap$EntryIterator.next
// at java.util.Collections$3.nextElement
}
*/
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
try {
unmodifiableMap.put("key4", "unmodifiableMap");
} catch (java.lang.UnsupportedOperationException e) {
System.err.println("UnsupportedOperationException : "+ e.getMessage() );
}
}
static void sleepThread( int sec ) {
try {
Thread.sleep( 1000 * sec );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
« Null Kunci Dan Nilai-Nilai Null
HashMap
memungkinkan maksimum satu null kunci dan sejumlah nilai-nilai null. Di mana sebagai Hashtable
tidak memungkinkan bahkan satu null key dan nilai null, jika kunci atau nilai null maka melempar NullPointerException. Contoh
Hashtable
secara internal disinkronkan. Oleh karena itu, hal ini sangat aman untuk digunakan Hashtable
di multi threaded aplikasi. Di mana sebagai HashMap
tidak disinkronkan secara internal. Oleh karena itu, hal ini tidak aman untuk digunakan HashMap
di multi threaded aplikasi tanpa sinkronisasi eksternal. Anda dapat eksternal sinkronisasi HashMap
menggunakan Koleksi.synchronizedMap()
metode.
« Kinerja
Sebagai Hashtable
secara internal disinkronkan, hal ini membuat Hashtable
sedikit lebih lambat dari HashMap
. @Lihat
1.Hashmap
dan HashTable
kedua toko kunci dan nilai.
2.Hashmap
dapat menyimpan salah satu kunci sebagai null
. Hashtable
dapat't toko null
.
3.HashMap
tidak disinkronkan tapi Hashtable
disinkronkan.
4.HashMap
dapat disinkronkan dengan Koleksi.SyncronizedMap(peta)
Map hashmap = new HashMap();
Map map = Collections.SyncronizedMap(hashmap);
Terlepas dari perbedaan-perbedaan yang telah disebutkan, perlu dicatat bahwa sejak Java 8, HashMap
dinamis menggantikan Node (linked list) yang digunakan pada masing-masing ember dengan TreeNodes (red-black tree), sehingga bahkan jika tinggi hash collisions ada, kasus terburuk ketika mencari adalah
O(log(n)) untuk HashMap
Vs O(n) dalam Hashtable
.
*Atas perbaikan belum diterapkan untuk Hashtable
belum, tapi hanya untuk HashMap
, LinkedHashMap
, dan ConcurrentHashMap
.
FYI, saat ini,
TREEIFY_THRESHOLD = 8
: jika sebuah ember berisi lebih dari 8 node, linked list adalah berubah menjadi seimbang pohon.UNTREEIFY_THRESHOLD = 6
: ketika ember menjadi terlalu kecil (karena penghapusan atau resize) pohon dikonversi kembali ke linked list.