java中HashMap和HashTable的区别是什么?HashMap和HashTable的简单比较
本篇文章给大家带来的内容是java中HashMap和HashTable的区别是什么?HashMap和HashTable的简单比较。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助。
1.首先来看下继承结构:
HashMap
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
Hashtable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
1、首先通过名字我们可以看出HashMap符合驼峰命名规则,Hashtable不符合驼峰命名规则,通过继承结构我们发现HashMap继承自AbstractMap
2、通过类的属性可以发现,在jdk1.8,当HashMap中的某条链中存储的结点数大于等于8时并且链表数组长度大于64时转化为红黑树,而Hashtable并不会转化为红黑树。
3、Hashtable的put()与HashMap的put()
Hashtable的put操作:
public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }
Hashtable中的方法添加了synchronized 关键字,所以它是一个同步方法。
通过 if (value == null) throw new NullPointerException();} 可以看出他不允许value的值为空,而当key为null时,调用key.hashCode();会抛出null指针异常,所以Hashtable中存储的Entry中的key和值都不能为空。还有Hashtable取链表下标是通过%运算来取的。
下面看HashMap
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
可以看到HashMap中key可以有一个null,当key为null空时它的hash值为0,而且HashMap获取链表数组下标的方法与Hashtable不同,它是使用(n-1)&hash来计算,因为HashMap的数组链表长度为2的n次方。
总结:HashMap中的key可以有一个null,值可以有多个null,Hashtable中的key和value都不能为空。定位链的方式不同,HashMap通过&运算来获取下标,而Hashtable通过%来获取下标,&运算更快。
4、HashMap和Hashtable的扩容方式不同。
Hashtable扩容:
@SuppressWarnings("unchecked") protected void rehash() { int oldCapacity = table.length; Entry<?,?>[] oldMap = table; // overflow-conscious code int newCapacity = (oldCapacity << 1) + 1; //MAX_ARRAY_SIZE = int的最大值-8 if (newCapacity - MAX_ARRAY_SIZE > 0) { if (oldCapacity == MAX_ARRAY_SIZE) // Keep running with MAX_ARRAY_SIZE buckets return; newCapacity = MAX_ARRAY_SIZE; } Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; modCount++; threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1); table = newMap; //从链表数组尾到头遍历 for (int i = oldCapacity ; i-- > 0 ;) { for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) { Entry<K,V> e = old; old = old.next; //从新定位链位置 int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = (Entry<K,V>)newMap[index]; newMap[index] = e; } } }
通过源码我们发现Hashtable链表数组的最大长度为int类型的最大值-8,Hashtable的扩容会把长度变为原来的二倍加1,而且扩容后需要从新定位链表。而且扩容后数组链表的顺序变成了原顺序的倒序。
HashMap的扩容:
final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; //如果远链表数组长度大于零 if (oldCap > 0) { //如果原长度大于或等于MAXIMUM_CAPACITY(2^30),则将threshold(闸值)设为Integer.MAX_VALUE大约为MAXIMUM_CAPACITY(2^30)的二倍 if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } //让新的容量变为旧的二倍 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) //新的闸值也变为原来的二倍 newThr = oldThr << 1; // double threshold } //老的链表数组长度小于等于0,老的闸值大于零,这种情况是初始化时传入一个map导致的构造器为public HashMap(Map<? extends K, ? extends V> m) else if (oldThr > 0) // initial capacity was placed in threshold //让新的容量等于旧的闸值 newCap = oldThr; //下面的else是默认的构造器,即public HashMap() else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } //新的闸值为零时(也就是(newCap = oldCap << 1) >= MAXIMUM_CAPACITY的情况),这时需要赋予newThr正确的值。 if (newThr == 0) { float ft = (float)newCap * loadFactor; //闸值=链表数组长度*加载因子。 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; //扩容,如果原来的链表数组中有数据,就复杂到table中 @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; if (oldTab != null) { //遍历老的链表数组 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; //当oldTab[j]这条链不为空时 if ((e = oldTab[j]) != null) { oldTab[j] = null; //如果这条链只有首节点有数据,把它添加进新链表数组中 if (e.next == null) //因为数组的容量时2的n次方,所以使用hash&(newCap-1)来计算出在那条链中。 newTab[e.hash & (newCap - 1)] = e; //如果老的链在红黑树中,使用split()方法来复制 else if (e instanceof TreeNode) ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); //当前链中不只只有一个链表头数据时,遍历链表来复制 else { // preserve order //数据的复制有两种情况,第一种是原位置不变,第二种是位置改变 loHead代表和原链相同位置的链,hiHead代表是原链加上原容量的链,因为扩容后长度为原长度的二倍,一个链中的节点要不在原位置的链中,要么在原位置加原容量的链中 Node<K,V> loHead = null, loTail = null; Node<K,V> hiHead = null, hiTail = null; Node<K,V> next; do { next = e.next; //通过e.hash和oldCap进行&运算来得出位置是否需要改变。 比如原数组容量为16(10000)和hash值进行&运算,如果高位1未参加运算,则为0即位置不变,如果高位参加了运算值不等于0,需要改变位置。 //loHead和hiHead分别代表原位置的链和新位置的链 if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); if (loTail != null) { loTail.next = null; //原位置为j newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; //新位置为j+oldCap newTab[j + oldCap] = hiHead; } } } } } return newTab; }
可以看到HashMap的扩容容量变为原来的二倍,而且它不需要从新定位链表,因为扩容后的位置要么在原位置,要么在原位置+原容量,通过hash和链表数组的长度进行与运算即可判断,如果数组长度的高位参加了运算就在原位置+原容量,高位没参加运算在原位置。而且HashMap扩容后链表数据顺序不变。
5.HashMap和Hashtable的初始容量不同。
Hashtable的初始容量为11,HashMap的初始容量为16.
Atas ialah kandungan terperinci java中HashMap和HashTable的区别是什么?HashMap和HashTable的简单比较. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Mekanisme pengembangan peta hash adalah untuk mengira semula kapasiti dan menggantikan tatasusunan asal dengan tatasusunan baharu. Kira semula semua data tatasusunan asal dan masukkan tatasusunan baharu, kemudian tuding ke tatasusunan baharu jika tatasusunan telah mencapai nilai maksimum sebelum pengembangan kapasiti, tetapkan ambang terus kepada integer maksimum dan kembalikannya.

Cara memasukkan pasangan nilai kunci ke dalam HashMap menggunakan kaedah put() kelas HashMap ialah kelas yang sangat penting dalam rangka kerja pengumpulan Java. Ia menyediakan cara untuk menyimpan pasangan nilai kunci. Dalam pembangunan sebenar, kita selalunya perlu memasukkan pasangan nilai kunci ke dalam HashMap, yang boleh dicapai dengan mudah dengan menggunakan kaedah put() kelas HashMap. Tandatangan kaedah put() HashMap adalah seperti berikut: Vput(Kkey,Vvalue)

Memasukkan nilai kunci pendua dalam javaHashMap Untuk memasukkan nilai pendua dalam HashMap, anda perlu terlebih dahulu memikirkan cara elemen disimpan dalam HashMap. Setiap elemen yang disimpan dalam kaedah put Map ialah pasangan nilai kunci, dan semuanya ditambah melalui kaedah put, dan kunci yang sama hanya akan mempunyai satu nilai yang berkaitan dalam Peta. Kaedah meletakkan ditakrifkan seperti berikut dalam Peta. Pelaksanaan kaedah Vput(Kkey,Vvalue);put(): pertama cincang(kunci) mendapat kod cincang() kunci, dan peta cincang mencari rantai di mana kedudukan yang hendak dimasukkan adalah berdasarkan kod cincang yang diperolehi.

1. Jelaskan bahawa Map pada asasnya boleh menggunakan HashMap, tetapi HashMap mempunyai masalah, iaitu, susunan lelaran HashMap bukanlah susunan HashMap diletakkan, atau ia tidak teratur. Kekurangan HashMap ini sering menyebabkan masalah, kerana dalam sesetengah senario kami menjangkakan Peta tersusun, iaitu LinkedHashMap. 2. Contoh perbezaan publicstaticvoidmain(String[]args){Mapmap=newLinkedHashMap();map.put("apple","Apple");map.put("

Tafsiran dokumentasi Java: Penjelasan terperinci tentang penggunaan kaedah containsKey() bagi kelas HashMap Contoh kod khusus diperlukan. Kaedah containsKey() digunakan untuk menentukan sama ada HashMap mengandungi kunci yang ditentukan. Artikel ini akan menerangkan secara terperinci cara menggunakan kaedah containsKey() kelas HashMap dan memberikan contoh kod khusus. 1. samb

1. Apakah corak tunggal? Corak tunggal ialah corak penciptaan objek yang digunakan untuk menjana contoh tertentu objek Ia boleh memastikan bahawa hanya satu contoh kelas dalam sistem dijana. Singleton yang dilaksanakan dalam Java adalah dalam skop mesin maya Oleh kerana fungsi memuatkan kelas adalah milik mesin maya, mesin maya akan mencipta contoh kelas apabila ia memuatkan kelas tunggal melalui ClassLoadnya sendiri. Dalam bahasa Java, tingkah laku sedemikian boleh membawa dua faedah utama: 1. Untuk objek yang kerap digunakan, masa yang dihabiskan untuk mencipta objek boleh diabaikan, yang merupakan overhed sistem yang sangat besar untuk objek berwajaran berat tersebut 2. Sejak bilangan operasi baharu; dikurangkan, kekerapan penggunaan memori sistem juga akan dikurangkan, yang akan mengurangkan tekanan GC.

JavaMap ialah struktur data yang biasa digunakan dalam perpustakaan standard Java, yang menyimpan data dalam bentuk pasangan nilai kunci. Prestasi Map adalah penting untuk kecekapan menjalankan aplikasi Jika prestasi Map adalah lemah, ia boleh menyebabkan aplikasi berjalan perlahan atau ranap. 1. Pilih pelaksanaan Peta yang sesuai Java menyediakan pelbagai pelaksanaan Peta, termasuk HashMap, TreeMap dan LinkedHashMap. Setiap pelaksanaan Peta mempunyai kelebihan dan keburukan tersendiri Apabila memilih pelaksanaan Peta, anda perlu memilih pelaksanaan yang sesuai berdasarkan keperluan khusus aplikasi. HashMap: HashMap ialah pelaksanaan Peta yang paling biasa digunakan Ia menggunakan jadual cincang untuk menyimpan data dan mempunyai kelajuan pemasukan, pemadaman dan carian yang lebih pantas.

Java menggunakan fungsi putAll() kelas HashMap untuk menambahkan Map ke Map lain ialah struktur data yang biasa digunakan dalam Java dan digunakan untuk mewakili koleksi pasangan nilai kunci. Dalam rangka kerja pengumpulan Java, HashMap ialah kelas pelaksanaan yang biasa digunakan. Ia menyediakan fungsi putAll(), yang digunakan untuk menambah satu Peta ke Peta lain untuk memudahkan penggabungan dan penyalinan data. Artikel ini akan memperkenalkan cara menggunakan fungsi putAll() dan memberikan contoh kod yang sepadan. pertama,
