Java 逆引き集 | LinkedHashMap(挿入順/アクセス順保持) — LRU 実装の簡易版

Java Java
スポンサーリンク

LinkedHashMap(挿入順/アクセス順保持) — LRU 実装の簡易版

Java の LinkedHashMap は、HashMap に「順序保持機能」を追加したものです。
初心者が理解すべきポイントは「挿入順/アクセス順を保持できる」「LRU(Least Recently Used)キャッシュを簡単に作れる」ということです。ここでは例題を交えて解説します。


LinkedHashMap の特徴

  • HashMap と同じくキーと値を管理(検索は平均 O(1))。
  • 順序保持:
    • 挿入順: 追加した順番を保持。
    • アクセス順: get/put でアクセスした順番を保持。
  • LRU キャッシュの簡易実装: removeEldestEntry をオーバーライドすれば、古い要素を自動削除できる。

👉 用途: 「順序付きのマップ」「キャッシュ機構」「最近使ったデータの管理」。


基本コード例

1. 挿入順保持

import java.util.LinkedHashMap;

public class InsertOrderDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        map.put("A", "Apple");
        map.put("B", "Banana");
        map.put("C", "Cherry");

        System.out.println(map); // {A=Apple, B=Banana, C=Cherry}
    }
}
Java

👉 HashMap だと順序は保証されないが、LinkedHashMap は挿入順を保持。


2. アクセス順保持

import java.util.LinkedHashMap;
import java.util.Map;

public class AccessOrderDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>(16, 0.75f, true);

        map.put("A", "Apple");
        map.put("B", "Banana");
        map.put("C", "Cherry");

        // アクセス
        map.get("A");
        map.get("B");

        System.out.println(map); // {C=Cherry, A=Apple, B=Banana}
    }
}
Java

👉 コンストラクタの第3引数 true で「アクセス順保持」に切り替え。
👉 最近アクセスした要素が末尾に移動する。


LRU キャッシュの簡易版

LinkedHashMap を継承して removeEldestEntry をオーバーライドすると、最大サイズを超えたら古い要素を自動削除できます。

例題: LRU キャッシュ

import java.util.LinkedHashMap;
import java.util.Map;

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int maxSize;

    public LRUCache(int maxSize) {
        super(16, 0.75f, true); // アクセス順保持
        this.maxSize = maxSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > maxSize; // サイズ超過で最古の要素削除
    }
}

public class LRUCacheDemo {
    public static void main(String[] args) {
        LRUCache<Integer, String> cache = new LRUCache<>(3);

        cache.put(1, "One");
        cache.put(2, "Two");
        cache.put(3, "Three");
        cache.get(1); // 1 をアクセス → 最近使用扱い
        cache.put(4, "Four"); // サイズ超過 → 最古の 2 が削除

        System.out.println(cache); // {3=Three, 1=One, 4=Four}
    }
}
Java

👉 動き:

  • 最大サイズ 3。
  • 4 を追加した時点で最古の「2」が削除される。
  • 最近アクセスした「1」は残る。

テンプレート集

挿入順保持

LinkedHashMap<K, V> map = new LinkedHashMap<>();
Java

アクセス順保持

LinkedHashMap<K, V> map = new LinkedHashMap<>(initialCapacity, loadFactor, true);
Java

LRU キャッシュ

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int maxSize;
    public LRUCache(int maxSize) { super(16, 0.75f, true); this.maxSize = maxSize; }
    @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > maxSize;
    }
}
Java

実務でのコツ

  • キャッシュ用途: DBやAPIの結果をキャッシュして高速化。
  • 順序付き出力: ログや履歴を「追加順」で保持したいときに便利。
  • アクセス順での管理: 最近使ったデータを優先的に残す仕組みが簡単に作れる。
  • スレッド安全: LinkedHashMap はスレッドセーフではない。複数スレッドで使う場合は Collections.synchronizedMapConcurrentHashMap を検討。

まとめ

  • LinkedHashMap は「順序保持できる HashMap」。
  • 挿入順/アクセス順を選べる。
  • LRU キャッシュは removeEldestEntry を使えば簡単に実装可能。

👉 練習課題として「最大5件まで保持する LRU キャッシュ」を作り、アクセス順に並び替えながらデータを追加してみると、LinkedHashMap の便利さが体感できます。

タイトルとURLをコピーしました