Java WeakHashMap:理解、活用、主要な違い
Java WeakHashMap
JavaのWeakHashMapについて、作成方法、HashMapとの主な違い、実践例、必須メソッドを包括的に解説します。
Javaコレクションフレームワークの一部であるWeakHashMapクラスは、Mapインターフェースを実装します。通常のハッシュテーブルのように振る舞いますが、キーを弱参照として格納するため、キーがもはや使用されなくなるとガベージコレクタによって回収されます。
プログラムがキー オブジェクトへの強参照を保持しなくなると、弱参照はガベージコレクトの対象となります。
WeakHashMapの作成
まずjava.util.WeakHashMapをインポートします:
import java.util.WeakHashMap;
次にインスタンス化し、オプションで初期容量と負荷係数を指定:
// 容量8、負荷係数0.6のWeakHashMap
WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8, 0.6);
パラメータ:
- capacity - リサイズ前のエントリ数。デフォルトは16
- loadFactor - マップ拡張の閾値。デフォルトは0.75
パラメータなしの場合、デフォルト値が適用されます:
WeakHashMap<Key, Value> numbers = new WeakHashMap<>();
HashMap vs WeakHashMap
両方ともMapを実装しますが、主要な違いは参照強度にあります:
- HashMap - キーは強参照。エントリは明示的に削除されるまで持続
- WeakHashMap - キーは弱参照。キーが到達不能になるとエントリが消滅
動作を示す例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("WeakHashMap: " + numbers);
// キーへの参照をnull化
two = null;
System.gc();
System.out.println("GC後のWeakHashMap: " + numbers);
}
}
出力:
WeakHashMap: {Four=4, Two=2}
GC後のWeakHashMap: {Four=4}
"Two"のエントリは、そのキーがもはや強到達不能になったため消滅します。対照的にHashMapはエントリを保持します:
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> numbers = new HashMap<>();
String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("HashMap: " + numbers);
two = null;
System.gc();
System.out.println("GC後のHashMap: " + numbers);
}
}
出力:
HashMap: {Four=4, Two=2}
GC後のHashMap: {Four=4, Two=2}
したがって、WeakHashMapは未使用キーに結びついたメモリを自動的に解放したい場合に最適です。
他のマップからの変換
既存マップからWeakHashMapをインスタンス化してエントリをコピー:
import java.util.HashMap;
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> evenNumbers = new HashMap<>();
String two = new String("Two");
evenNumbers.put(two, 2);
System.out.println("HashMap: " + evenNumbers);
WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers);
System.out.println("WeakHashMap: " + numbers);
}
}
出力:
HashMap: {Two=2}
WeakHashMap: {Two=2}
WeakHashMapの主要メソッド
最も頻繁に使用される操作の選択です。
エントリの挿入
put(key, value)- マッピングを追加putAll(map)- 他のマップをマージputIfAbsent(key, value)- キーが存在しない場合のみ挿入
例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>();
evenNumbers.put(new String("Two"), 2);
evenNumbers.putIfAbsent(new String("Four"), 4);
System.out.println("偶数: " + evenNumbers);
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.putAll(evenNumbers);
System.out.println("すべての数: " + numbers);
}
}
出力:
偶数: {Four=4, Two=2}
すべての数: {Two=2, Four=4, One=1}
エントリへのアクセス
以下でデータを取得:
get(key)- 値を返す。存在しない場合はnullgetOrDefault(key, default)- キーが欠落時はデフォルトを返すentrySet()、keySet()、values()- エントリ、キー、値をイテレーション
例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.put(new String("Two"), 2);
System.out.println("Map: " + numbers);
System.out.println("エントリセット: " + numbers.entrySet());
System.out.println("キー: " + numbers.keySet());
System.out.println("値: " + numbers.values());
System.out.println("Twoを取得: " + numbers.get("Two"));
System.out.println("FourのgetOrDefault: " + numbers.getOrDefault("Four", 4));
}
}
出力:
Map: {Two=2, One=1}
エントリセット: [Two=2, One=1]
キー: [Two, One]
値: [1, 2]
Twoを取得: 2
FourのgetOrDefault: 4
エントリの削除
remove(key)- 削除して値を返すremove(key, value)- 現在のマッピングが指定値と一致する場合のみ削除clear()- マップを空にするcontainsKey(key)、containsValue(value)、size()、isEmpty()
例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.put(new String("Two"), 2);
System.out.println("Map: " + numbers);
int removed = numbers.remove("Two");
System.out.println("削除された値: " + removed);
boolean removedIf = numbers.remove("One", 3);
System.out.println("{One=3}は削除されたか? " + removedIf);
System.out.println("削除後: " + numbers);
}
}
出力:
Map: {Two=2, One=1}
削除された値: 2
{One=3}は削除されたか? false
削除後: {One=1}
その他のユーティリティ
| メソッド | 説明 |
|---|---|
clear() | すべてのエントリを削除 |
containsKey(key) | キーの存在確認 |
containsValue(value) | 値の存在確認 |
size() | エントリ数を返す |
isEmpty() | エントリがなければtrue |
詳細については公式Java WeakHashMapドキュメントを参照してください。
Java
- Java演算子をマスター:種類、構文、実践例
- Javaコメント:種類、使い方、ベストプラクティス
- Java if…elseをマスター:制御フローを徹底解説
- Java拡張forループをマスター:構文、例、ベストプラクティス
- Java文字列をマスター:生成、メソッド、ベストプラクティス
- Javaインターフェース完全ガイド:概念、実装、ベストプラクティス
- Java無名インナークラス完全ガイド:定義、構文、実践例
- Javaのtry-with-resourcesをマスターする:自動リソース管理の仕組みと活用法
- Javaアノテーション完全ガイド:種類、配置場所、実践例
- Javaアサーション完全ガイド:バグ早期発見とコード信頼性の向上
- Java Vectorの理解:使い方、特徴、ArrayListとの比較