1. はじめに
Javaにおける双方向集合は、主にキーと値のペアを格納するためのコレクション型です。この中で最も一般的に使用されるのは、Mapインターフェースおよびその実装クラスです。これらの集合はデータをキーと値のペアとして管理し、キーを使って迅速に値にアクセスすることができます。
2. **HashMap**
HashMapはハッシュテーブルに基づいて作成されたMapインタフェースの実装クラスで、nullキーとnull値をサポートします。基本的な操作(挿入、削除、検索)は平均的にO(1)の時間計算量を持ちますが、順序を保証しません。
内部的には配列と連結リスト、またはJDK8以降では赤黒木が使用されます。初期容量は16で、負荷係数は0.75です。拡張時にはサイズが2倍になります。
// HashMapの生成
Map<String, Integer> map = new HashMap<>();
// 要素の追加
map.put("りんご", 1);
map.put("バナナ", 2);
// 値の取得
int value = map.get("りんご");
System.out.println(value); // 出力: 1
3. **LinkedHashMap**
LinkedHashMapはHashMapを継承しており、要素の挿入順序を保持します。また、LRU(Least Recently Used)キャッシュアルゴリズムに対応したアクセス順序にも対応可能です。
内部構造はハッシュテーブルと二重に連結されたリストからなります。
// LinkedHashMapの生成
Map<String, Integer> linkedMap = new LinkedHashMap<>(16, 0.75f, true);
// 要素の追加
linkedMap.put("りんご", 1);
linkedMap.put("バナナ", 2);
// 値の取得とアクセス順序の更新
int value = linkedMap.get("りんご");
System.out.println(value); // 出力: 1
4. **TreeMap**
TreeMapは赤黒木を使用して実装されており、キーの自然順序やカスタム比較子による順序を維持します。
// TreeMapの生成
Map<String, Integer> treeMap = new TreeMap<>();
// 要素の追加
treeMap.put("りんご", 1);
treeMap.put("バナナ", 2);
// 値の取得
int value = treeMap.get("りんご");
System.out.println(value); // 出力: 1
5. **Hashtable**
Hashtableは古いMapクラスで、同期制御によりスレッドセーフですが、パフォーマンス上の理由でConcurrentHashMapへの置き換えが推奨されています。
// Hashtableの生成
Map<String, Integer> table = new Hashtable<>();
// 要素の追加
table.put("りんご", 1);
table.put("バナナ", 2);
// 値の取得
int value = table.get("りんご");
System.out.println(value); // 出力: 1
6. **ConcurrentHashMap**
ConcurrentHashMapは高スレッド並列性を考慮して設計され、分節ロック(Segmented lock)によってスレッドセーフを実現しています。
// ConcurrentHashMapの生成
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
// 要素の追加
concurrentMap.put("りんご", 1);
concurrentMap.put("バナナ", 2);
// 値の取得
int value = concurrentMap.get("りんご");
System.out.println(value); // 出力: 1
7. **Properties**
Propertiesクラスは、Hashtableを継承し、設定ファイルの読み書きに使われます。主に`.properties`形式のファイルを扱います。
// プロパティの生成と設定
Properties prop = new Properties();
prop.setProperty("db.url", "jdbc:mysql://localhost:3306/mydatabase");
// ファイルからの読み込み
try (FileInputStream fis = new FileInputStream("config.properties")) {
prop.load(fis);
} catch (IOException e) {
e.printStackTrace();
}
// ファイルへの保存
try (FileOutputStream fos = new FileOutputStream("config.properties")) {
prop.store(fos, "Database Configuration");
} catch (IOException e) {
e.printStackTrace();
}