2次元のキーを持つハッシュデータを作るJavaTips 〜Javaプログラミング編

» 2004年08月24日 10時00分 公開
[佐藤匡剛@IT]

 IDによって管理されているデータベース上のデータのように、キーと値が対となるデータを扱わなければならないことはよくあります。そのようなときは、コアAPIのjava.utilパッケージにある、HashMapクラスやDictionaryクラスを利用するのが一般的でしょう。

 しかし、2つのキーの組み合わせで値が特定されるようなデータにも直面することがあります。例えば、各都道府県の年齢別人口といったデータでは、「都道府県」と「年齢」という2つのキーによって、人口を特定しなくてはなりません。

 このような2次元のキーを持つデータを扱うときは、どのクラスを使えばいいのでしょうか? HashMapクラスやDictionaryクラスは、1つのキーだけで値を一意に特定できるデータには問題なく使えますが、このようなデータはうまく処理することができません。実際のところ、複数キーを持つデータを扱うためのクラスは、コアAPIには用意されていません。従って、複数キーを持つデータを扱えるようなオブジェクトを、自分で用意する必要があります。

 本稿では、2次元のキーを持つデータを作成する典型的な方法を2つ紹介します。どちらも、コアAPIにあるクラスのインスタンスを組み合わせることで実現します。

HashMap + HashMap

 まず、java.util.HashMapを2回用いる方法です。アイデアとしては、HashMapの値をさらにHashMapオブジェクトにすることで、2次元キーのデータを表現する、というものです。

図

 以下は、HashMapを2回用いた方法のサンプルコードです。ここでは、先ほど例に挙げた各都道府県の年齢別の人口を、2次元キーのデータとして表現しています。「東京都」「25歳」という2つのキーに対し、「234567人」という値を対応付けています。

TwoKeysMap.java
package net.mogra.wings.javatips;

import java.util.HashMap;
import java.util.Map;

public class TwoKeysMap {

  public static void main(String[] args) {
    String prefecture = "東京都";             // キー1
    Integer age = new Integer(25);            // キー2
    Integer population = new Integer(234567); // 値

    // データの格納
    Map twoKeysMap = new HashMap();
    twoKeysMap.put(prefecture, new HashMap());
    ((Map) twoKeysMap.get(prefecture)).put(age, population);

    // データの取り出し
    System.out.println("(東京都, 25歳)の人口 = "
        + ((Map) twoKeysMap.get("東京都")).get(new Integer(25))
        + " 人");
  }
}


 このサンプルコードの実行結果は次のとおりです。

実行結果
> javac net\mogra\wings\javatips\TwoKeysMap.java
> java net.mogra.wings.javatips.TwoKeysMap
(東京都, 25歳)の人口 = 234567 人


 この方法では、2次元キーのデータを表すHashMapオブジェクト(サンプルではtwoKeysMap)が、値としてHashMapオブジェクトを持つことを常に意識しながらコードを書かなくてはならないため、多少の注意が必要になります。一方、1つ目のキー(サンプルでは都道府県)が同一なデータをすべて取り出す、といった操作が容易に行えるという特徴があります。

ArrayList + HashMap

 もう1つは、java.util.ArrayListとjava.util.HashMapとを用いる方法です。アイデアとしては、キーをArrayListオブジェクトにすることで、キーの多次元性を表現するというものです。

図

 こちらの方法のサンプルコードは、以下のようになります。例として取り上げているデータは、前述のTwoKeysMap.javaと同じものです。また、実行結果もTwoKeysMap.javaと同様です。

TwoKeysMap2.java
package net.mogra.wings.javatips;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TwoKeysMap2 {

  public static void main(String[] args) {
    String prefecture = "東京都";             // キー1
    Integer age = new Integer(25);            // キー2
    Integer population = new Integer(234567); // 値

    // データの格納
    Map twoKeysMap2 = new HashMap();
    List keys = new ArrayList();
    keys.add(prefecture);
    keys.add(age);
    twoKeysMap2.put(keys, population);

    // データの取り出し
    List keys2 = new ArrayList();
    keys2.add("東京都");
    keys2.add(new Integer(25));
    System.out.println("(東京都, 25歳)の人口 = "
        + twoKeysMap2.get(keys2)
        + " 人");
  }
}


 こちらの方法では、キーの多次元性をArrayListオブジェクトで表現しているため、ハッシュデータそのものは単なるHashMapオブジェクトとして扱え、操作が直感的で容易です。一方、1つ目のキーが同じデータをすべて取り出すという操作は、最初に紹介した方法に比べるとかなり難しくなります。

 どちらの方法を採用するかは、そのデータを使ってどのような操作をするかによって、適切に選択すればよいでしょう。また、どちらの方法にしても、少し応用するだけで、キーを3つ以上持つような多次元キーのデータ表現へ、簡単に拡張することができます。

 本稿では、既存のコアAPIのクラスのインスタンスを組み合わせることで、2次元キーのデータを扱う方法を紹介しました。しかし、システムの中でこのようなデータ構造が頻繁に使われたり、あるいは、それがシステムの中で特定の意味を持っているようであれば、新たなクラスを用意することをお勧めします。もちろん、そのようなクラスは、ここでご紹介した方法を応用して実装することができます。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。