Java の HashMap と Hashtable の比較: 主な違いと効率

Java の HashMap と Hashtable の比較: 主な違いと効率
Java

Java の HashMap と Hashtable を理解する

Java コレクションの世界では、HashMap と Hashtable は、キーと値のペアを格納するために広く使用されている 2 つのデータ構造です。これらは似ているように見えますが、アプリケーションのパフォーマンスとスレッドの安全性に影響を与える可能性のある明確な違いがあります。ニーズに合ったものを選択するには、これらの違いを理解することが重要です。

この記事では、HashMap と Hashtable の主な違いを詳しく掘り下げ、その機能、効率性、非スレッド アプリケーションへの適合性を探ります。最終的には、特定のユースケースでどのデータ構造を使用するかがより明確になるでしょう。

指示 説明
HashMap.put() キーと値のペアを HashMap に挿入します。 null キーと値を許可します。
Hashtable.put() キーと値のペアをハッシュテーブルに挿入します。 null キーまたは値は許可されません。
System.nanoTime() 実行中の Java 仮想マシンの高解像度タイム ソースの現在値をナノ秒単位で返します。
try { ... } catch (NullPointerException e) コードの実行を試み、NullPointerExceptions をキャッチし、Hashtable.put() が null 値で呼び出された場合を処理します。
HashMap.get() 指定されたキーに関連付けられた値を HashMap から取得します。
Hashtable.get() 指定されたキーに関連付けられた値をハッシュテーブルから取得します。

HashMap とハッシュテーブルの実装の詳細

最初のスクリプトは、次のことを直接比較します。 HashMap そして Hashtable ジャワでは。スクリプトは、必要なクラスをインポートし、両方のデータ構造のインスタンスを作成することから始まります。あ HashMap インスタンス化され、キーと値のペアが設定されます。同様に、 Hashtable が作成され、設定されます。次に、このスクリプトは、 値の処理における基本的な違いを示します。 HashMap.put() null 値を問題なく挿入できますが、 Hashtable.put() を投げます NullPointerException null キーまたは値を追加しようとした場合。の try { ... } catch (NullPointerException e) ブロックは、この動作を説明するために使用されます。このスクリプトは、開発者がこれら 2 つのデータ構造のどちらかを選択する際に、Null 値が考慮される時期と理由を理解するのに役立ちます。

2 番目のスクリプトは、次のパフォーマンス テストに焦点を当てています。 HashMap そして Hashtable 非スレッド環境では。まず、両方のマップを初期化し、次を使用して 100 万個のキーと値のペアを挿入するのにかかる時間を測定します。 System.nanoTime()。この高解像度の時間測定は、操作にかかった時間を正確に把握するのに役立ちます。結果はコンソールに出力され、相対的なパフォーマンスが示されます。このスクリプトは、両方のデータ構造からの同じキーのセットの取得時間も測定します。これらの時間を比較することで、開発者は非スレッド アプリケーションでどのデータ構造のパフォーマンスが優れているかを判断できます。このスクリプトは、パフォーマンスの調整と、関連するオーバーヘッドの理解に特に役立ちます。 Hashtable 同期されたメソッドのため。

HashMap と Hashtable の比較: 主な違いと使用例

比較のための Java 実装

import java.util.HashMap;
import java.util.Hashtable;

public class MapComparison {
    public static void main(String[] args) {
        // Creating a HashMap
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("1", "One");
        hashMap.put("2", "Two");
        hashMap.put("3", "Three");

        // Creating a Hashtable
        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("A", "Apple");
        hashtable.put("B", "Banana");
        hashtable.put("C", "Cherry");

        // Displaying the HashMap
        System.out.println("HashMap: " + hashMap);

        // Displaying the Hashtable
        System.out.println("Hashtable: " + hashtable);

        // Checking for null values
        try {
            hashMap.put(null, "NullValue");
            System.out.println("HashMap allows null values: " + hashMap);
        } catch (NullPointerException e) {
            System.out.println("HashMap does not allow null values");
        }
        try {
            hashtable.put(null, "NullValue");
            System.out.println("Hashtable allows null values: " + hashtable);
        } catch (NullPointerException e) {
            System.out.println("Hashtable does not allow null values");
        }
    }
}

HashMap と Hashtable: シングルスレッド環境でのパフォーマンス

非スレッドアプリケーションの Java パフォーマンステスト

import java.util.HashMap;
import java.util.Hashtable;

public class PerformanceTest {
    public static void main(String[] args) {
        // Initializing the maps
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        Hashtable<Integer, Integer> hashtable = new Hashtable<>();

        // Adding elements to HashMap
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashMap.put(i, i);
        }
        long endTime = System.nanoTime();
        System.out.println("HashMap time: " + (endTime - startTime) + " ns");

        // Adding elements to Hashtable
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashtable.put(i, i);
        }
        endTime = System.nanoTime();
        System.out.println("Hashtable time: " + (endTime - startTime) + " ns");

        // Retrieving elements from HashMap
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashMap.get(i);
        }
        endTime = System.nanoTime();
        System.out.println("HashMap retrieval time: " + (endTime - startTime) + " ns");

        // Retrieving elements from Hashtable
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashtable.get(i);
        }
        endTime = System.nanoTime();
        System.out.println("Hashtable retrieval time: " + (endTime - startTime) + " ns");
    }
}

HashMap と Hashtable: 同期とスレッド セーフ

両者の主な違いの 1 つは、 HashMap そして Hashtable これは、同期とスレッドの安全性に対する彼らのアプローチです。 Hashtable 同期されています。つまり、スレッドセーフであり、同時実行の問題を引き起こすことなく複数のスレッド間で共有できます。この同期は、ほとんどのメソッドを同期させることで実現され、これにより、常に 1 つのスレッドだけがハッシュテーブルにアクセスできるようになります。ただし、これにより、ロック機構によるパフォーマンスのオーバーヘッドも発生します。 Hashtable に比べて遅い HashMap シングルスレッドのシナリオの場合。

対照的に、 HashMap 同期されていないため、スレッドセーフではありません。もし HashMap 複数のスレッドによって同時にアクセスされると、データの不整合や競合状態が発生するリスクがあります。作ります HashMap スレッドセーフで開発者が使用できる Collections.synchronizedMap() 同期されたマップでラップするか、 ConcurrentHashMap Java 1.5 で導入されたクラス。マップのさまざまな部分への同時アクセスを可能にすることでパフォーマンスが向上します。これにより、 ConcurrentHashMap 同時アプリケーションにとってはより効率的な選択肢となります。

HashMap と Hashtable に関するよくある質問

  1. HashMap と Hashtable の主な違いは何ですか?
  2. HashMap は同期されていないため、null キーと値が許可されますが、 Hashtable は同期されており、null キーまたは値は許可されません。
  3. シングルスレッド環境ではどちらが速いでしょうか?
  4. HashMap シングルスレッド環境では、同期オーバーヘッドがないため、一般に高速になります。
  5. HashMap をスレッドセーフにするにはどうすればよいでしょうか?
  6. を使用することで Collections.synchronizedMap() を包む HashMap または使用して ConcurrentHashMap
  7. Hashtable は null キーまたは値を格納できますか?
  8. いいえ、 Hashtable null キーまたは値は許可されず、 NullPointerException 試みた場合。
  9. HashMap ではなく Hashtable を使用する必要があるのはどのような場合ですか?
  10. 使用 Hashtable スレッド セーフが必要であり、同期のパフォーマンス オーバーヘッドを気にしない場合。
  11. ConcurrentHashMap は Hashtable のより良い代替手段ですか?
  12. はい、 ConcurrentHashMap と比較して優れた同時実行性とパフォーマンスを提供します。 Hashtable
  13. HashMap がスレッドセーフではないのはなぜですか?
  14. HashMap はシングルスレッドのシナリオ向けに設計されており、同期メカニズムは含まれていません。
  15. HashMap と Hashtable は衝突をどのように処理しますか?
  16. 両方 HashMap そして Hashtable チェーンを使用して衝突を処理します。各バケットにはエントリのリンクされたリストが含まれます。

HashMap と Hashtable についての最終的な考え

HashMap と Hashtable は、キーと値のペアを保存するという点で同様の目的を果たしますが、同期とパフォーマンスへのアプローチが大きく異なります。 HashMap は、その速度と null 値の柔軟性により、非スレッド アプリケーションに推奨されます。逆に、Hashtable はスレッドセーフな操作に適していますが、パフォーマンスが犠牲になります。これらの違いを理解することで、開発者は特定の要件に基づいてどのデータ構造を使用するかについて情報に基づいた決定を下すことができます。