• ベストアンサー

独自クラスをVectorに格納してindexOfで検索する方法

ewuals(myclass)、ewuals(int)とhash()を実装した、自分で作成したクラスがあります。 そのクラスをVectorに格納して、indexOf()やlastIndeOf()で検索しようとしていますが、-1が返されます。 for()ループとequals()を使用して自分で検索すると、意図した値が帰ってくるのですが。どこがいけないのでしょうか? ===>java -version java version "1.6.0_11" Java(TM) SE Runtime Environment (build 1.6.0_11-b03) Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing) import java.util.Vector; ===>type equaltest.java class equaltest { public static void main(String args[]) { myclass myc[] = new myclass[8]; myc[0] = new myclass(false, 10 , 3); myc[1] = new myclass(false, 10 , 4); myc[2] = new myclass(false, 20 , 3); myc[3] = new myclass(false, 20 , 4); myc[4] = new myclass(true, 10 , 3); myc[5] = new myclass(true, 10 , 4); myc[6] = new myclass(true, 20 , 3); myc[7] = new myclass(true, 20 , 4); //Vectorに追加 Vector<myclass> myVec = new Vector<myclass>(); for (int lp1 = 0; lp1<myc.length;lp1++){ myVec.add(myc[lp1]); } //Vectorの中身を表示 System.out.println(myVec.toString()); System.out.println("------------"); System.out.println("Vector.indexOfの返す値は・・・"); System.out.println("10\t:"+myVec.indexOf(10)); System.out.println("20\t:"+myVec.indexOf(20)); System.out.println("3\t:"+myVec.indexOf(3)); System.out.println("4\t:"+myVec.indexOf(4)); myclass mytmp = new myclass(true, 20 , 4); //mytmpの中身を表示 System.out.println(mytmp.toString()); System.out.println("mytmp\t:"+myVec.indexOf(mytmp)); System.out.println("自分でequals比較すると・・・"); System.out.println("mytmp?2\t:"+mytmp.equals(myc[2])); System.out.println("mytmp?3\t:"+mytmp.equals(myc[3])); System.out.println("mytmp?4\t:"+mytmp.equals(myc[4])); System.out.println("mytmp(10):"+mytmp.equals(10)); System.out.println("mytmp(20):"+mytmp.equals(20)); System.out.print("自分でVectorを検索すると・・・["); for (int lp1 = 0; lp1<=myVec.size();lp1++){ if(lp1 == myVec.size()){ System.out.println("-1(not found)]"); break; } if(mytmp.equals((myclass)(myVec.elementAt(lp1))) == true){ System.out.println("" + lp1 + "]"); break; } } } } ===>type myclass.java public class myclass{ boolean flg; int valurT; int valurF; // myclass(){ flg = false; valurT = 20; valurF = 5; } myclass(boolean af, int avalurT, int avalurF){ flg = af; valurT = avalurT; valurF = avalurF; } // public boolean equals(int myArg){ if(flg){ return (valurT == myArg); }else{ return (valurF == myArg); } } // public boolean equals(myclass argmycls){ if(flg){ return (valurT == argmycls.valurT); }else{ return (valurF == argmycls.valurF); } } public String toString(){ return "[flg:"+flg+" valurT:"+valurT+" valurF:"+valurF+"]"; } public int hashCode(){ if(flg){ return (valurT); }else{ return (valurF); } } }

質問者が選んだベストアンサー

  • ベストアンサー
  • azumaiya
  • ベストアンサー率100% (5/5)
回答No.2

適切な関数がオーバーライドされていないためです。 Vector などのコレクションでは同じかどうかの比較に equals(Object) を使用します。 そのため、equals(int), equals(myclass) などのような独自関数を 定義してもコレクション内部では使用されません。 例えば、サンプルコードのように indexOf() に int を入れても位置を 取得したいときには、myclass に以下の関数を定義する必要があります。 boolean equals(Object obj) {  if(obj instanceof Integer) {   int i = ((Integer)obj).intValue();   if(flg){    return (valurT == i);   }else{    return (valurF == i);   }  }  return super.equals(obj); } このように、引数の Object が Integer かどうかを判断して適切に 場合分けをする equals(Object) を実装しておかなくてはいけません。 Vector.indexOf() に myclass を入れる場合も、同様に equals(Object) を改良する必要があります。

osu_neko09
質問者

お礼

ありがとうございました。equals(Object) を改良する必要があります、というのは予想外でした。 以下の関数を追加して実装したら、myclass 同士の比較はうまくいくようになりました。 public boolean equals(Object obj) { if(obj instanceof Integer) { int i = ((Integer)obj).intValue(); return(this.equals(i)); }else if (obj instanceof myclass) { myclass myc = ((myclass)obj); return(this.equals(myc)); } return super.equals(obj); }

その他の回答 (3)

  • azumaiya
  • ベストアンサー率100% (5/5)
回答No.4

すいません。前回の回答に一部間違いがありました。 コレクション内部で equals(Object) が呼び出されるのは正しいのですが、ww-_-ww さんの回答にありますように indexOf() で呼び出されるのは、「<引数>.equals(<要素>)」です。 myclass の方でうまくいったのは、indexOf() の引数として渡される myclass が適切に equals(Object) をオーバーライドしていたためです。 一方、int の場合には indexOf() に実際に渡されるのは Integer クラスとなりますが、こちらは myclass に対する適切な処理が施されている equals(Object) を持っていません。 このため、myclass ではうまくいくが、int ではうまくいかないということになってしまっています。 int を指定して要素を取り出すときには、int をラップして equals(Object) をオーバーライドしたラッパーオブジェクトを引数として渡す必要があります。例としては以下の様なクラスです。 // クラス定義 class IntHolder {  int fInt;  public IntHolder(int i) {   fInt = i;  }  public equals(Object obj) {   if (obj instanceof myclass) {    myclass my = (myclass)obj;    return my.equals(fInt);   }   return super.equals(obj);  } } // 使用方法 int pos = myVec.indexOf(new IntHolder(10));

osu_neko09
質問者

お礼

ありがとうございます。こちらも、無事、動きました。 後で見る人のために一応補足しておきます。 class IntHolder は、publicでなくてよいので独立したクラスにしましょう。 class IntHolder を class equaltest の内部クラスにするとコンパイルが通りません。(「static でない 変数 this を static コンテキストから参照することはできません。」となります。) public boolean equals(Object obj) { でした。

  • ww-_-ww
  • ベストアンサー率51% (46/89)
回答No.3

NO1です。 >Integer.equals(Vector配列の(k)番目)、つまりindexOfの引数.equals(Vector配列のelementAt(k))という判断をしている、という理解でよろしいでしょうか。 そうですね。つまりこの場合はObjectのequalsメソッドで判定しているってことです。 >それにしても、こちらでも(同じクラスを使っていても)-1が返されるのがわかりません。 これについてはすでにNo2さんが回答している通り、メソッド(equals(Object))のオーバライドが足らないだけです。 ただ、equalsメソッドは完全一致だとほとんどの人は思うと思いますが、myclassだとフラグ分けしているので完全一致でなくても良いように見えますが、いいんですかね? ま、これは仕様の話ですか。

osu_neko09
質問者

お礼

なるほど、ということはIntegerで渡してしまうと myClassをオーバライドしても無駄、ということになりますね。 別のやり方を考えます。 >equalsメソッドは完全一致だと・・・ ええ、確かに普通は完全一致なのですが。こういうことを実現したくていろいろやっている最中でして。 1.表裏が区別できるカードに数字が書いてあります。 2.山札のカードは表裏ごっちゃになっている状態です。 3.表向きのカードが指示されたときには、山札から、「表向きになっていて表面に書いてある数字が一致する」カード(裏はどうでもよい)を、裏向きのカードが指示されたときには、山札から、「裏向きになっていて裏面に書いてある数字が一致する」カード(表はどうでもよい)を、探します。 #フラグの比較もつけてみたけれど思ったとおりには動かない^^;

  • ww-_-ww
  • ベストアンサー率51% (46/89)
回答No.1

VectorのindexOfの使い方がおかしいから。 Vector配列にint型の値は入ってないから-1が返却されるのは当たり前です。 System.out.println("10\t:"+myVec.indexOf(10));

osu_neko09
質問者

補足

>Vector配列にint型の値は入ってないから.... Integer.equals(Vector配列の(k)番目)、つまりindexOfの引数.equals(Vector配列のelementAt(k))という判断をしている、という理解でよろしいでしょうか。 それにしても、こちらでも(同じクラスを使っていても)-1が返されるのがわかりません。 System.out.println("mytmp\t:"+myVec.indexOf(mytmp));