HashMapとHashTableの違い、深い理解

HashMapとHashTableはどちらも、Key-Valueペアで格納されたコレクションオブジェクトです。それぞれに長所と短所がありますが、本日は両者の直接の違いについてお話します。

違いは次のとおりです。

  • HashMapのスレッドセーフな実行効率は高く、HashTableのスレッドセーフな実行効率は低い
  • HashMapは空のキーを保存でき、HashTableは空のキーを保存できません

次に、これら2つのポイントについて説明します。
1. HashMapスレッドセーフ実行効率は高く、HashTableスレッドセーフ実行効率は低い。
これは、HashMapの基になるメソッドがロックれておらず、同期によって変更されないため、実行効率が比較的速い一方で、基になるHashTableメソッドは同期で変更されるため、実行効率は比較的遅くなります。HashMap
のいくつかの主要なメソッドの
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
コードは次のとおりです。HashTableのコードは次のとおりです。
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
複数のスレッドが書き込み操作で同時に同じ変数を共有する場合、スレッドセーフの問題が発生する可能性があるため、同時実行性が高い場合、HashMapを使用するべきではありませんが、HashTableは最良の選択ではありません。最良の選択は、主に原則を使用するConcurrentHashMapセグメント化ロックであり、CASはロックなし(楽観的ロック)が
必要です。あなたはより深い理解を持っています、あなたはプログラマーXiaohuiによってこのブログをチェックすることができます

HashMapは空のキーを格納できますが、HashTableは空のキーを格納できません
。JDK1.7の方が理解しやすいため、JDK1.7のコードを確認できます。まず
HashMapのメソッドを見てください

// HashMap的put方法
 public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
             // key为null调用putForNullKey(value)
             return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
 
        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
 /**
     * Offloaded version of put for null keys
     */
    private V putForNullKey(V value) {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(0, null, value, 0);
        return null;
    }

HashMapのputメソッドの場合、2番目の判断はキーがnullであると判断し、putForNullKey(V value)メソッドを入力します。
前のforループは、テーブル[0]でキーがnullの要素を見つけることであることがわかります。リンクリスト。見つかった場合、値はこの要素の値に再割り当てされ、元の値が返されます。
上記のforループが見つからない場合は、この要素をtalbe [0]リンクリストの先頭に追加します。

HashTableはこの処理を行いませんでした。直接Keyを使用してhashCode値を計算します。この時点で、キーが取得されない場合、nullポインターエラー
ここに画像の説明を挿入
が報告されます。エラーがローカル
ここに画像の説明を挿入
HashMapで報告されていることがわかります。キーが空の場合はい、同時にhashCodeがないので、値はどこに格納されますか?デフォルトのストレージテーブル[0] hashMap1.7のコードから
、HashMapがキーを次のように格納できるかどうかを確認できます。オブジェクト?私たちが通常使用する一般的な文字列、オブジェクトなどはすべてオブジェクトで
ある
ため、この答えも可能です。
ここに画像の説明を挿入
現在のクラスの新しいオブジェクトをHashMapのキーとして使用し、値を正しく取得します。

拡張hashcodeとequal()の違いは何ですか
hashCode()メソッドとequal()メソッドは実際には同じです。Javaでは、2つのオブジェクトが等しいかどうかを比較するために使用されます。したがって、equal()はすでに達成できます。比較の関数。、なぜhashCode()?
書き直されたequal()は一般により包括的で複雑であるため、効率は比較的低く、比較にhashCode()を使用するだけで、比較用のハッシュ値を生成するだけで効率が高くなり、hashCode()がなぜ効率が非常に高くてもequal()ですか?
hashCode()は完全に信頼できるわけではないため、異なるオブジェクトが同じハッシュコードを生成することがあります(hashMapからリンクリストへのハッシュ衝突配列と同様に、ハッシュ値式の生成で発生する可能性のある問題)。したがって、hashCode()は次のようにしか言えません。ほとんどの場合、信頼できるが、絶対的に信頼できるわけではないので、次のことができます。

  • 1. equal()を持つ2つのオブジェクトのhashCode()は等しくなければなりません。つまり、equal()との比較は絶対に信頼できます。

  • 2. hashCode()が等しい2つのオブジェクトは、equal()が必ずしも等しいとは限りません。つまり、hashCode()は完全に信頼できるわけではありません。

    大量の高速比較が必要な場合、equal()を使用すると明らかに非効率的であるため、hashCode()が異なる場合は、比較する必要があるときはいつでも、最初にhashCode()を使用して比較します。 、thenこれら2つのオブジェクトが完全に等しくないことを示します(つまり、equal()を使用して比較する必要はありません)。hashCode()が同じ場合は、
    それらのequal()を比較します。equal()も同じ、つまり2つのオブジェクトが実際に同じであるため、効率が大幅に向上し、比較の絶対的な正確性が保証されます。

おすすめ

転載: blog.csdn.net/G_whang/article/details/112687708