Java : WeakHashMap (弱参照マップ) - API使用例

WeakHashMap (Java SE 18 & JDK 18) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

ハッシュ表に基づいた、弱キーによるMapインタフェースの実装です。 WeakHashMap内のエントリは、そのキーが普通に使われることがなくなると自動的に削除されます。 より正確には、指定されたキーのマッピングが存在しても、ガベージ・コレクタがキーを破棄するのを防ぐことはできません。

クラス構成

WeakHashMap は、弱参照 のキーを持つ Map です。
弱参照のキーが GC でクリアされると、マップから要素が自動的に削除されます。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();

var key1 = new Key("aaa");
var key2 = new Key("bbb");

map.put(key1, 100);
map.put(key2, 200);

System.out.println(map); // {bbb=200, aaa=100}

System.gc();

System.out.println(map); // {bbb=200, aaa=100}

key1 = null;
System.gc();

System.out.println(map); // {bbb=200}

key2 = null;
System.gc();

System.out.println(map); // {}

補足

  • 本記事のコード例では、GCを実行するために System.gc メソッドを使っています。
  • しかし、一般的なJavaプログラムでは、System.gc を直接呼び出すことはあまりおすすめしません。
    Javaシステムが自分自身の最適なタイミングでGCを実行してくれるためです。

コンストラクタ

WeakHashMap ()

デフォルトの初期容量(16)と負荷係数(0.75)を持つ、新しい空のWeakHashMapを作成します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
System.out.println(map); // {}
System.out.println(map.isEmpty()); // true

map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}
System.out.println(map.size()); // 3

WeakHashMap (int initialCapacity)

指定された初期容量とデフォルトの負荷係数(0.75)を持つ、新しい空のWeakHashMapを作成します。

初期容量を変えて処理時間を計った例です。
(実行する環境によって変わる可能性があります)

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>(10000000);
System.out.println(map); // {}

final var startTime = System.nanoTime();

for (int i = 0; i < 1000000; i++) {
    map.put(new Key(String.valueOf(i)), i);
}

final var endTime = System.nanoTime();

// 0.205931 sec.
System.out.printf("%f sec.%n", (endTime - startTime) / 1000000000.0);
final var map = new WeakHashMap<Key, Integer>(1);
System.out.println(map); // {}

final var startTime = System.nanoTime();

for (int i = 0; i < 1000000; i++) {
    map.put(new Key(String.valueOf(i)), i);
}

final var endTime = System.nanoTime();

// 0.278058 sec.
System.out.printf("%f sec.%n", (endTime - startTime) / 1000000000.0);

WeakHashMap (int initialCapacity, float loadFactor)

指定された初期容量と指定された負荷係数を持つ、新しい空のWeakHashMapを作成します。

負荷係数を変えて処理時間を計った例です。
(実行する環境によって変わる可能性があります)

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>(16, 0.05f);
System.out.println(map); // {}

final var startTime = System.nanoTime();

for (int i = 0; i < 1000000; i++) {
    map.put(new Key(String.valueOf(i)), i);
}

final var endTime = System.nanoTime();

// 0.367535 sec.
System.out.printf("%f sec.%n", (endTime - startTime) / 1000000000.0);
final var map = new WeakHashMap<Key, Integer>(16, 0.75f);
System.out.println(map); // {}

final var startTime = System.nanoTime();

for (int i = 0; i < 1000000; i++) {
    map.put(new Key(String.valueOf(i)), i);
}

final var endTime = System.nanoTime();

// 0.285230 sec.
System.out.printf("%f sec.%n", (endTime - startTime) / 1000000000.0);

WeakHashMap (Map<? extends K,? extends V> m)

指定されたマップと同じマッピングを持つ、新しいWeakHashMapを構築します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var m = Map.of(new Key("a"), 10, new Key("b"), 20, new Key("c"), 30);

final var map = new WeakHashMap<>(m);
System.out.println(map); // {a=10, c=30, b=20}
System.out.println(map.size()); // 3

メソッド

void clear ()

すべてのマッピングをマップから削除します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}
System.out.println(map.size()); // 3

map.clear();
System.out.println(map); // {}
System.out.println(map.size()); // 0

boolean containsKey (Object key)

指定されたキーのマッピングがこのマップに含まれている場合にtrueを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}

System.out.println(map.containsKey(new Key("a"))); // true
System.out.println(map.containsKey(new Key("b"))); // true
System.out.println(map.containsKey(new Key("c"))); // true
System.out.println(map.containsKey(new Key("X"))); // false
System.out.println(map.containsKey(new Key(""))); // false

boolean containsValue (Object value)

このマップが1つまたは複数のキーと指定された値をマッピングしている場合にtrueを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);
map.put(new Key("X"), 30);

System.out.println(map); // {X=30, a=10, c=30, b=20}

System.out.println(map.containsValue(0)); // false
System.out.println(map.containsValue(10)); // true
System.out.println(map.containsValue(20)); // true
System.out.println(map.containsValue(30)); // true
System.out.println(map.containsValue(40)); // false

Set<Map.Entry<K,V>> entrySet ()

このマップに含まれるマッピングのSetビューを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 1);
map.put(new Key("b"), 2);
map.put(new Key("c"), 3);

System.out.println(map); // {a=1, c=3, b=2}

final var entries = map.entrySet();
System.out.println(entries); // [a=1, c=3, b=2]

map.replace(new Key("b"), 20);
System.out.println(map); // {a=1, c=3, b=20}
System.out.println(entries); // [a=1, c=3, b=20]

entries.remove(Map.entry(new Key("a"), 1));
System.out.println(map); // {c=3, b=20}
System.out.println(entries); // [c=3, b=20]

for (final var entry : entries) {
    entry.setValue(entry.getValue() * 10);
}

System.out.println(map); // {c=30, b=200}
System.out.println(entries); // [c=30, b=200]

V get (Object key)

指定されたキーがマップされている値を返します。そのキーのマッピングがこのマップに含まれていない場合はnullを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}

System.out.println(map.get(new Key("a"))); // 10
System.out.println(map.get(new Key("b"))); // 20
System.out.println(map.get(new Key("c"))); // 30
System.out.println(map.get(new Key("X"))); // null
System.out.println(map.get(new Key(""))); // null

boolean isEmpty ()

このマップがキーと値のマッピングを保持しない場合にtrueを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}
System.out.println(map.size()); // 3
System.out.println(map.isEmpty()); // false

map.clear();

System.out.println(map); // {}
System.out.println(map.size()); // 0
System.out.println(map.isEmpty()); // true

Set<K> keySet ()

このマップに含まれるキーのSetビューを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}

final var keys = map.keySet();
System.out.println(keys); // [a, c, b]

map.put(new Key("d"), 40);
System.out.println(map); // {a=10, c=30, b=20, d=40}
System.out.println(keys); // [a, c, b, d]

keys.remove(new Key("a"));
System.out.println(map); // {c=30, b=20, d=40}
System.out.println(keys); // [c, b, d]

V put (K key, V value)

指定された値と指定されたキーをこのマップに関連付けます。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
System.out.println(map); // {}

System.out.println(map.put(new Key("a"), 1)); // null
System.out.println(map); // {a=1}

System.out.println(map.put(new Key("b"), 2)); // null
System.out.println(map); // {a=1, b=2}

System.out.println(map.put(new Key("c"), 3)); // null
System.out.println(map); // {a=1, c=3, b=2}

System.out.println(map.put(new Key("a"), 999)); // 1
System.out.println(map); // {a=999, c=3, b=2}

void putAll (Map<? extends K,? extends V> m)

指定されたマップからすべてのマッピングをマップにコピーします。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
System.out.println(map); // {}

map.putAll(Map.of());
System.out.println(map); // {}

map.putAll(Map.of(new Key("a"), 1, new Key("b"), 2));
System.out.println(map); // {a=1, b=2}

map.putAll(Map.of(new Key("c"), 3, new Key("d"), 4, new Key("e"), 5));
System.out.println(map); // {a=1, c=3, b=2, e=5, d=4}

map.putAll(Map.of(new Key("a"), 901, new Key("b"), 902, new Key("z"), 100));
System.out.println(map);  // {z=100, a=901, c=3, b=902, e=5, d=4}

V remove (Object key)

キーのマッピングがある場合に、そのマッピングをこの弱ハッシュ・マップから削除します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 10);
map.put(new Key("b"), 20);
map.put(new Key("c"), 30);

System.out.println(map); // {a=10, c=30, b=20}

System.out.println(map.remove(new Key("b"))); // 20
System.out.println(map); // {a=10, c=30}

System.out.println(map.remove(new Key("z"))); // null
System.out.println(map); // {a=10, c=30}

int size ()

このマップ内のキー値マッピングの数を返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();

System.out.println(map); // {}
System.out.println(map.size()); // 0

map.put(new Key("a"), 10);
System.out.println(map); // {a=10}
System.out.println(map.size()); // 1

map.put(new Key("b"), 20);
System.out.println(map); // {a=10, b=20}
System.out.println(map.size()); // 2

map.put(new Key("c"), 30);
System.out.println(map); // {a=10, c=30, b=20}
System.out.println(map.size()); // 3

Collection<V> values ()

このマップに含まれる値のCollectionビューを返します。

record Key(String s) {
    @Override
    public String toString() {
        return s;
    }
}

final var map = new WeakHashMap<Key, Integer>();
map.put(new Key("a"), 1);
map.put(new Key("b"), 2);
map.put(new Key("c"), 3);

System.out.println(map); // {a=1, c=3, b=2}

final var values = map.values();
System.out.println(values); // [1, 3, 2]

map.replace(new Key("b"), 20);
System.out.println(map); // {a=1, c=3, b=20}
System.out.println(values); // [1, 3, 20]

values.remove(1);
System.out.println(map); // {c=3, b=20}
System.out.println(values); // [3, 20]

//values.add(4); // UnsupportedOperationException

AbstractMapで宣言されたメソッド

clone, equals, hashCode, toString

Java API 使用例 : AbstractMap」をご参照ください。

Mapで宣言されたメソッド

compute, computeIfAbsent, computeIfPresent, equals, forEach, getOrDefault, hashCode, merge, putIfAbsent, remove, replace, replace, replaceAll

Java API 使用例 : Map」をご参照ください。


関連記事

ページの先頭へ