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. これは、HashMap のチェーンに格納されているノードの数が 8 以上であり、リンクされたリストの長さである場合、jdk1.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 キーワードを追加するため、A synchronized メソッドになります。
if (value == null) throw new NullPointerException();} を通して、value の値を空にすることは許可されておらず、キーが null の場合は key.hashCode() を呼び出していることがわかります。 ; null ポインタが異常であるため、ハッシュテーブルに格納されているエントリのキーと値を空にすることはできません。さらに、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 のキーが null の場合、そのハッシュ値は 0 になり、HashMap のメソッドがその値を取得することがわかります。リンクリスト配列の添え字はHashtableと同じですが、HashMapの配列リンクリストの長さは2のn乗なので、(n-1)&hashを使って計算されます。
概要: HashMap のキーには 1 つの null を含めることができ、値には複数の null を含めることができ、Hashtable のキーと値を空にすることはできません。チェーンを配置する方法は異なります。HashMap は & 操作を通じて添字を取得しますが、Hashtable は % を通じて添字を取得し、& 操作の方が高速です。
4. HashMap と 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; } } }
ソース コードを通じて、ハッシュテーブルのリンク リスト配列の最大長が int 型の最大値 -8 であることがわかりました。元の長さの 2 倍に 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 の展開容量が 2 倍になっていることがわかります。展開された位置は元の位置または元の位置にあるため、リンク リストの位置を変更する必要はありません。位置の元の容量は、ハッシュとリンクされたリスト配列の長さの AND 演算によって決定できます。配列の長さの上位ビットが計算に関与する場合、元の容量は元の位置になります。配列長の上位ビットが計算に参加しない場合、元の容量は元の位置になります。また、リンクリストデータの順序は、HashMap展開後も変化しません。
5. HashMap と Hashtable の初期容量は異なります。
Hashtable の初期容量は 11、HashMap の初期容量は 16 です。
以上がJavaのHashMapとHashTableの違いは何ですか? HashMap と HashTable の単純な比較の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











ハッシュマップの拡張メカニズムは、容量を再計算し、元の配列を新しい配列に置き換えることです。元の配列のすべてのデータを再計算し、新しい配列を挿入し、新しい配列をポイントします。配列が容量拡張前の最大値に達している場合は、しきい値を最大の整数に直接設定して返します。

HashMap クラスの put() メソッドを使用して、キーと値のペアを HashMap に挿入する方法。HashMap は、Java コレクション フレームワークの非常に重要なクラスです。キーと値のペアを格納する方法を提供します。実際の開発では、多くの場合、キーと値のペアを HashMap に挿入する必要があります。これは、HashMap クラスの put() メソッドを使用することで簡単に実現できます。 HashMap の put() メソッドのシグネチャは次のとおりです: Vput(Kkey,Vvalue)

javaHashMap に重複する Key 値を挿入する HashMap に重複する値を挿入するには、まず要素が HashMap にどのように格納されるかを理解する必要があります。 put メソッド Map に格納される各要素はキーと値のペアであり、それらはすべて put メソッドを通じて追加され、Map 内で同じキーに関連付けられる値は 1 つだけになります。 Mapではputメソッドを以下のように定義しています。 Vput(Kkey,Vvalue); put() メソッドの実装: 最初に hash(key) でキーの hashcode() を取得し、取得したハッシュコードに基づいて挿入される位置のチェーンを hashmap で見つけます。

Java ドキュメントの解釈: HashMap クラスの containsKey() メソッドの使用法の詳細な説明 特定のコード例が必要です はじめに: HashMap は Java で一般的に使用されるデータ構造であり、効率的なストレージおよび検索機能を提供します。 containsKey() メソッドは、HashMap に指定されたキーが含まれているかどうかを判断するために使用されます。この記事では、HashMap クラスの containsKey() メソッドの使用方法を詳しく説明し、具体的なコード例を示します。 1.続き

1. Map は基本的に HashMap を使用できますが、HashMap には問題があります。つまり、HashMap の反復順序が HashMap の配置順序と異なっているか、順序が狂っていることを説明します。 HashMap のこの欠点は、多くの場合問題を引き起こします。これは、シナリオによっては、順序付けされた Map (LinkedHashMap) が期待されるためです。 2. 相違点インスタンス publicstaticvoidmain(String[]args){Mapmap=newLinkedHashMap();map.put("apple","Apple");map.put("

1. シングルトン パターンとは何ですか?シングルトン パターンは、オブジェクトの特定のインスタンスを生成するために使用されるオブジェクト作成パターンであり、システム内のクラスのインスタンスが 1 つだけ生成されるようにすることができます。 Java で実装されたシングルトンは仮想マシンのスコープ内にあり、クラスをロードする機能は仮想マシンに属するため、仮想マシンは独自の ClassLoad を通じてシングルトン クラスをロードするときにクラスのインスタンスを作成します。 Java 言語では、このような動作により 2 つの大きな利点がもたらされます: 1. 頻繁に使用されるオブジェクトの場合、オブジェクトの作成にかかる時間を省略できます。これは、これらの重量のあるオブジェクトにとって非常に大きなシステム オーバーヘッドになります; 2. 新しい操作の数が増えるため、が減少すると、システム メモリの使用頻度も減少し、GC 圧力が軽減されます。

Java は、HashMap クラスの putAll() 関数を使用して、Map を別の Map に追加します。Map は Java で一般的に使用されるデータ構造であり、キーと値のペアのコレクションを表すために使用されます。 Java のコレクション フレームワークでは、HashMap が一般的に使用される実装クラスです。これは putAll() 関数を提供します。この関数は、あるマップを別のマップに追加して、データのマージとコピーを容易にするために使用されます。この記事では、putAll() 関数の使用方法と、対応するコード例を紹介します。初め、

JavaMap は、Java 標準ライブラリで一般的に使用されるデータ構造であり、キーと値のペアの形式でデータを格納します。 Map のパフォーマンスは、アプリケーションの実行効率にとって非常に重要です。Map のパフォーマンスが低いと、アプリケーションの実行が遅くなったり、クラッシュしたりする可能性があります。 1. 適切な Map 実装を選択します。Java には、HashMap、TreeMap、LinkedHashMap などのさまざまな Map 実装が用意されています。各 Map 実装には独自の長所と短所があるため、Map 実装を選択するときは、アプリケーションの特定のニーズに基づいて適切な実装を選択する必要があります。 HashMap: HashMap は最も一般的に使用される Map 実装であり、ハッシュ テーブルを使用してデータを保存し、挿入、削除、検索の速度が速くなります。
