【Java学習|豆知識】Java開発の現場で差がつく!LinkedHashMapで順序を制御するスマートな方法

1. 導入:なぜLinkedHashMapが必要なのか

Javaで最もよく使われるMap実装であるHashMapは、非常に高速ですが「順序が保持されない」という特性があります。そのため、データを追加した順に表示したい場合や、最後にアクセスした要素を優先的に処理したい場合、HashMapでは対応できません。ここで登場するのがjava.util.LinkedHashMapです。順序を維持することで、履歴管理やキャッシュの実装など、実務で頻出する課題をシンプルに解決できます。

2. 基礎知識:LinkedHashMapの仕組み

LinkedHashMapはHashMapのサブクラスであり、内部的に「二重連結リスト」を保持しています。このリストによって、要素間の順序を管理しています。
特筆すべきは「挿入順(Insertion-order)」「アクセス順(Access-order)」の2つのモードがある点です。デフォルトは挿入順ですが、コンストラクタでアクセス順を指定すると、getメソッドで呼び出された要素が「最後にアクセスされたもの」として順序が更新されます。

3. 実装・解決策

順序を制御したい場合は、コンストラクタ引数に注目しましょう。
・挿入順:デフォルトのコンストラクタを使用。
・アクセス順:new LinkedHashMap<>(initialCapacity, loadFactor, true) と記述し、第3引数に true を渡します。
これを活用することで、LRU(Least Recently Used:最近使われていないものを捨てる)キャッシュのような仕組みも容易に作成可能です。

4. サンプルプログラム

以下のコードは、アクセス順を維持するLinkedHashMapの動作例です。

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

public class LinkedHashMapExample {
    public static void main(String[] args) {
        // 第3引数にtrueを渡してアクセス順モードにする
        // initialCapacity: 16, loadFactor: 0.75
        Map accessOrderMap = new LinkedHashMap<>(16, 0.75f, true);

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

        // "A" にアクセスして、順序を最後に更新する
        accessOrderMap.get("A");

        // 表示順序は B, C, A となる (Aが最後にアクセスされたため)
        System.out.println("アクセス順のマップ: " + accessOrderMap);
    }
}

5. 応用・注意点:現場での活用と落とし穴

応用:LRUキャッシュの実装
LinkedHashMapの removeEldestEntry メソッドをオーバーライドすると、指定したサイズを超えた際に自動で古い要素を削除するキャッシュが作れます。これはシニアエンジニアが頻繁に使うテクニックです。

注意点:スレッドセーフではない
LinkedHashMapはHashMapと同様にスレッドセーフではありません。マルチスレッド環境で共有する場合は、Collections.synchronizedMap を使用するか、ConcurrentHashMapの代替手段を検討してください。また、頻繁な要素の追加・削除がある場合は、内部の二重連結リストの更新コストが発生するため、HashMapよりわずかにオーバーヘッドがあることを念頭に置いて設計しましょう。

コメント

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