javax.vecmath.Vector2dクラスの挙動

Java幾何学を扱うときには、javax.vecmath パッケージのお世話になる。
javax.vecmath パッケージには、ベクトルを扱うために便利な Vector2d クラスや Vector3d クラスが含まれる。

このベクトルクラスについて、見事にはまったことがあったので、以下は備忘目的で。

Vector2d クラスおよび Vector3d クラスは、通常のオブジェクト指向の感覚で使用すると痛い目にあう。
むしろ、Vector2d や Vector3d は、Stringクラスまたは、Double や Integer クラスと同じようなものだと考えた方がいい。

たとえば、ArrayListVector、HashMapなどのコレクションに格納して、contains メソッドを使う時、オブジェクトの比較ではなく、値の比較が行われるので要注意。

具体例を示す。

Vector2d v0 = new Vector2d(1.0, 1.0);
Vector2d v1 = new Vector2d(2.0, 1.0);

ArrayList<Vector2d> array = new ArrayList<Vector2d>();
array.add(v0);
System.out.println(array.contains(v1));

上記では、ArrayList に v0 を格納して、その後で、ArrayList に v1 が含まれるかどうかを確認している。
もちろん出力は

false

になる。

では、次のコードはどうだろう。先ほどのコードに対して、v1の座標値だけ変更した。

Vector2d v0 = new Vector2d(1.0, 1.0);
Vector2d v1 = new Vector2d(1.0, 1.0); // ここだけ変更

ArrayList<Vector2d> array = new ArrayList<Vector2d>();
array.add(v0);
System.out.println(array.contains(v1));

なんと出力は

true

になる。

ArrayList に含まれるか否かの判断は、オブジェクトとしてのVector2dではなく、その値の比較によって行われるということだ。
これを知らないでいると、たとえば、Vector2d をキーとした HashMapを作ってしまった場合などに、どつぼにはまることになる(私だ)。

詳しくは、Vector2dクラスのスーパークラスである Tuple2d のAPI仕様書をみると、次のように記述されていることから、値の比較によって行われることがわかる。

boolean equals(Tuple2d t1)
Returns true if all of the data members of Tuple2d t1 are equal to the corresponding data members in this Tuple2d.

http://docs.oracle.com/cd/E17802_01/j2se/javase/technologies/desktop/java3d/forDevelopers/j3dapi/javax/vecmath/Tuple2d.html

つまり、ArrayList クラスの contains メソッドなどは、格納しているオブジェクトの equals メソッドを使って「同一オブジェクトであるか否か」の判断をしているが、
Vector2d クラスは、このequalsメソッドをオーバーライドしていて、ベクトルの2つの値が同じであるかによって判断されるようになっている。

ちなみに、Tuple2d クラスは、hashCode メソッドもオーバーライドしていて、ハッシュ値は内部の値によって生成されることになっている。

だから、HashMapのキーとして使うときは注意が必要だ(というか使うべきではない)。

int hashCode()
Returns a hash number based on the data values in this object.

http://docs.oracle.com/cd/E17802_01/j2se/javase/technologies/desktop/java3d/forDevelopers/j3dapi/javax/vecmath/Tuple2d.html

コレクションクラスや、オブジェクトの equals メソッドのオーバーライドに関する話は、次の書籍に詳しく書かれている。

Java 2 アプリケーションづくりの初歩 (CD-ROM付) (プログラミング学習シリーズ)

Java 2 アプリケーションづくりの初歩 (CD-ROM付) (プログラミング学習シリーズ)