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 とハッシュテーブルの実装の詳細
最初のスクリプトは、次のことを直接比較します。 そして ジャワでは。スクリプトは、必要なクラスをインポートし、両方のデータ構造のインスタンスを作成することから始まります。あ インスタンス化され、キーと値のペアが設定されます。同様に、 Hashtable が作成され、設定されます。次に、このスクリプトは、 値の処理における基本的な違いを示します。 null 値を問題なく挿入できますが、 を投げます null キーまたは値を追加しようとした場合。の try { ... } catch (NullPointerException e) ブロックは、この動作を説明するために使用されます。このスクリプトは、開発者がこれら 2 つのデータ構造のどちらかを選択する際に、Null 値が考慮される時期と理由を理解するのに役立ちます。
2 番目のスクリプトは、次のパフォーマンス テストに焦点を当てています。 そして 非スレッド環境では。まず、両方のマップを初期化し、次を使用して 100 万個のキーと値のペアを挿入するのにかかる時間を測定します。 。この高解像度の時間測定は、操作にかかった時間を正確に把握するのに役立ちます。結果はコンソールに出力され、相対的なパフォーマンスが示されます。このスクリプトは、両方のデータ構造からの同じキーのセットの取得時間も測定します。これらの時間を比較することで、開発者は非スレッド アプリケーションでどのデータ構造のパフォーマンスが優れているかを判断できます。このスクリプトは、パフォーマンスの調整と、関連するオーバーヘッドの理解に特に役立ちます。 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 つは、 そして これは、同期とスレッドの安全性に対する彼らのアプローチです。 同期されています。つまり、スレッドセーフであり、同時実行の問題を引き起こすことなく複数のスレッド間で共有できます。この同期は、ほとんどのメソッドを同期させることで実現され、これにより、常に 1 つのスレッドだけがハッシュテーブルにアクセスできるようになります。ただし、これにより、ロック機構によるパフォーマンスのオーバーヘッドも発生します。 Hashtable に比べて遅い シングルスレッドのシナリオの場合。
対照的に、 同期されていないため、スレッドセーフではありません。もし 複数のスレッドによって同時にアクセスされると、データの不整合や競合状態が発生するリスクがあります。作ります スレッドセーフで開発者が使用できる Collections.synchronizedMap() 同期されたマップでラップするか、 Java 1.5 で導入されたクラス。マップのさまざまな部分への同時アクセスを可能にすることでパフォーマンスが向上します。これにより、 同時アプリケーションにとってはより効率的な選択肢となります。
- HashMap と Hashtable の主な違いは何ですか?
- は同期されていないため、null キーと値が許可されますが、 は同期されており、null キーまたは値は許可されません。
- シングルスレッド環境ではどちらが速いでしょうか?
- シングルスレッド環境では、同期オーバーヘッドがないため、一般に高速になります。
- HashMap をスレッドセーフにするにはどうすればよいでしょうか?
- を使用することで を包む または使用して 。
- Hashtable は null キーまたは値を格納できますか?
- いいえ、 null キーまたは値は許可されず、 試みた場合。
- HashMap ではなく Hashtable を使用する必要があるのはどのような場合ですか?
- 使用 スレッド セーフが必要であり、同期のパフォーマンス オーバーヘッドを気にしない場合。
- ConcurrentHashMap は Hashtable のより良い代替手段ですか?
- はい、 と比較して優れた同時実行性とパフォーマンスを提供します。 。
- HashMap がスレッドセーフではないのはなぜですか?
- はシングルスレッドのシナリオ向けに設計されており、同期メカニズムは含まれていません。
- HashMap と Hashtable は衝突をどのように処理しますか?
- 両方 そして チェーンを使用して衝突を処理します。各バケットにはエントリのリンクされたリストが含まれます。
HashMap と Hashtable は、キーと値のペアを保存するという点で同様の目的を果たしますが、同期とパフォーマンスへのアプローチが大きく異なります。 HashMap は、その速度と null 値の柔軟性により、非スレッド アプリケーションに推奨されます。逆に、Hashtable はスレッドセーフな操作に適していますが、パフォーマンスが犠牲になります。これらの違いを理解することで、開発者は特定の要件に基づいてどのデータ構造を使用するかについて情報に基づいた決定を下すことができます。