- PR -

HashMapのキー情報を後から参照するには?

1
投稿者投稿内容
マリン
常連さん
会議室デビュー日: 2006/05/28
投稿数: 41
投稿日時: 2008-09-01 02:21
JDK5でDBテーブルのレコードを表現する以下のようなクラスがあります。
コード:
public class SamplePojo {
    private String id;
    private Integer field;

    public SamplePojo() { }

    public SamplePojo(String id) {
        this.id = id;
    }

    public SamplePojo(String id, Integer field) {
        this.id = id;
        this.field = field;
    }

// 〜getter/setter省略〜

    public boolean equals(Object other) {
        if (this == other ) return true;
        if ( !(other instanceof SamplePojo) ) return false;
        SamplePojo castOther = (SamplePojo)other;
        return new EqualsBuilder()
            .append(this.getId(), castOther.getId())
            .isEquals();
    }

    public int hashCode() {
        return new HashCodeBuilder()
            .append(getId())
            .toHashCode();
    }

}



このSamplePojoをキーとして別の値を持たせるHashMapを使う場合、equalsとhashCodeのオーバーライドにより実際にはid情報のみがキーとなるため、以下のようにmapに色々データを格納した後の処理ではidのみをセットしたSamplePojoとcontainsKeyメソッドでキーの存在チェックをすることができますが、実際にそのキーとして使われたSamplePojoのfield値の方を参照したい場合にはどうすればよいでしょうか?
entrySetやkeySetのループで再検索するのは非効率だと思うので、HashMapの値の方にもキーと同じSamplePojoを格納しておくようにするしかないでしょうか?

コード:
public class Test {
    public static void main(String[] args) {
        Map<SamplePojo, String> map = new HashMap<SamplePojo, String>();
        SamplePojo key = new SamplePojo("Pojo1", Integer.valueOf(0));
        map.put(key, "a");
        // 〜他にもmapにデータを格納する処理〜

        // 既存キーの検索・参照
        SamplePojo find = new SamplePojo("Pojo1");
        if (map.containsKey(find)) {
            System.out.println("実際のkeyのfieldは?");
        }
    }
}


unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-09-01 06:59
(私は POJO などは良く知らないのですが、それ以外のことについて書きます。)

まず、Map の Key として使うクラスは、equals で同一性を検査するものであるため、後からそのインスタンスを気にするような設計は、キレイではないと思います。設計段階ではじくべきだろうと思います。

すでにそういう設計にしているので、そのまま進みたいということで考えますと、Map に getKey というメソッドがあればそれで解決できることなのでしょうが、現実にはそういうメソッドはないし、HashMap のクラスを extends などして改造するのも、アクセス修飾子の問題があるので面倒かもしれません。どこかのクラスライブラリーには getKey 相当のものが付いているものもあるかもしれませんが。

引用:

マリンさんの書き込み (2008-09-01 02:21) より:
entrySetやkeySetのループで再検索するのは非効率だと思うので、HashMapの値の方にもキーと同じSamplePojoを格納しておくようにするしかないでしょうか?


Value のほうに入れる分には問題ないと思います。これが良いと思います。
ただし、Key と Value に同じもの(クラス)を入れるというのも冗長性があって、ちょっと気にはなります。
未記入
大ベテラン
会議室デビュー日: 2008/02/07
投稿数: 115
投稿日時: 2008-09-01 11:44
equals メソッドと hashCode メソッドをオーバーライドして、同一性がゆるやかにしているから、横着したくなるのかもしれないけど…。

SamplePojo("Pojo1") から SamplePojo("Pojo1", Integer.valueOf(0)) を探したいというのは、"Pojo1" から SamplePojo("Pojo1", Integer.valueOf(0)) を探したいということに他ならない。

ならば、HashMap<String, SamplePojo> を新たに作成し、String id から SamplePojo key を検索できるようにするのが正道ではないかな。
マリン
常連さん
会議室デビュー日: 2006/05/28
投稿数: 41
投稿日時: 2008-09-01 14:08
ご回答ありがとうございます。
unibon様がおっしゃるようにgetKeyのようなものがないかと思っており、KeyとValueの両方に同じものを入れるのも少し無駄な気がしていました。

HibernateのMiddlegenツールでコード生成するとSamplePojoのようなクラスができたので、HashMapに格納することによりメモリ上でも簡易DB的な使い方ができるかと思ったのですが、やはりidからkeyインスタンス全体を参照できるようにValueにも入れるか、別のHashMapを用意するのが自然、ということでデータ構造と処理を考え直してみることにします。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)