前回の続きです。今回はコード解説を行います。
TableMapは2次元のMapを表すインターフェースです。Mapに対して実装がHashMapとかTreeMapとかあるように、
2次元のMapを表すインターフェースを作り、実装をきりかえれるようにしてみました。
AxisEntryは2次元Mapをループで処理するときに利用するMap.Entryの実装です。
class AxisEntry<T1, T2, V> implements Map.Entry<T1, Map<T2, V>> {
というように、キー部分をジェネリクスで型を可変としているのでX軸→Y軸でループさせる場合にも、Y軸→X軸でループさせる場合にも
どういつのクラスを利用することが出来るようになっています。
値の取得
値を取得するget()メソッドの中を見てみましょう。
// hashCodeの取得、格納位置の特定
int indexX = getIndexX(this.map, x);
int indexY = getIndexY(this.map, y);
TableEntry<KX, KY, V> entry = this.map[indexX][indexY];
まずは、キーからインデックスを算出し、2次元配列であるthis.map
からTableEntryオブジェクトを取得します。
/** ハッシュ値を正の整数化するためのマスク */
private static final int HASH_CODE_MASK = 0x7FFFFFFF;
private int getIndexX(TableEntry[][] targetMap, KX x) {
int indexX = x.hashCode();
indexX &= HASH_CODE_MASK;
indexX %= targetMap.length;
return indexX;
}
インデックスの算出メソッドは上記のようになっており、ここでは
Object#hashCode()
の値を正の整数にして配列の長さで割った余りを利用しています。
if (entry == null) {
return null;
}
if (entry.getKeyX().equals(x)
&& entry.getKeyY().equals(y)) {
// トップが同一キーの場合
return entry.getValue();
}
// 単方向リストを走査
while (entry.getNext() != null) {
TableEntry<KX, KY, V> nextEntry = entry.getNext();
if (nextEntry.getKeyX().equals(x)
&& nextEntry.getKeyY().equals(y)) {
// 同一キーが見つかった場合
return nextEntry.getValue();
}
entry = nextEntry;
}
// 見つからなかった場合
return null;
ハッシュ値から算出したインデックスに重複することがないのであれば楽なのですが、実際にはそういうわけには行きませんので、
TableEntryオブジェクトは単方向リストのデータ構造を持つようにしてあり、getNext()で次のTableEntryに繋がるようになっています。
ループでまわしてキーが一致するオブジェクトを探し、見つかればその値を、最後まで見つからなければnullを返すようにしています。
長くなってきましたので続きはまた次回に。
投稿日時 : 2007年9月26日 12:03