プロが教えるわが家の防犯対策術!

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)
importjava.util.Vector;
===>type equaltest.java
class equaltest {

public static void main(String args[]) {
myclassmyc[]=newmyclass[8];
myc[0]=newmyclass(false,10,3);
myc[1]=newmyclass(false,10,4);
myc[2]=newmyclass(false,20,3);
myc[3]=newmyclass(false,20,4);
myc[4]=newmyclass(true,10,3);
myc[5]=newmyclass(true,10,4);
myc[6]=newmyclass(true,20,3);
myc[7]=newmyclass(true,20,4);

//Vectorに追加
Vector<myclass>myVec=newVector<myclass>();
for (intlp1=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));

myclassmytmp=newmyclass(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 (intlp1=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
publicclass myclass{
booleanflg;
intvalurT;
intvalurF;
//
myclass(){
flg=false;
valurT=20;
valurF=5;
}
myclass(booleanaf,intavalurT,intavalurF){
flg=af;
valurT=avalurT;
valurF=avalurF;
}
//
publicbooleanequals(intmyArg){
if(flg){
return(valurT==myArg);
}else{
return(valurF==myArg);
}
}

//
publicbooleanequals(myclassargmycls){
if(flg){
return(valurT==argmycls.valurT);
}else{
return(valurF==argmycls.valurF);
}
}

publicStringtoString(){
return"[flg:"+flg+" valurT:"+valurT+" valurF:"+valurF+"]";
}

public int hashCode(){
if(flg){
return(valurT);
}else{
return(valurF);
}
}
}

A 回答 (4件)

VectorのindexOfの使い方がおかしいから。



Vector配列にint型の値は入ってないから-1が返却されるのは当たり前です。

System.out.println("10\t:"+myVec.indexOf(10));

この回答への補足

>Vector配列にint型の値は入ってないから....
Integer.equals(Vector配列の(k)番目)、つまりindexOfの引数.equals(Vector配列のelementAt(k))という判断をしている、という理解でよろしいでしょうか。

それにしても、こちらでも(同じクラスを使っていても)-1が返されるのがわかりません。
System.out.println("mytmp\t:"+myVec.indexOf(mytmp));

補足日時:2009/01/20 13:36
    • good
    • 0

適切な関数がオーバーライドされていないためです。


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) を改良する必要があります。
    • good
    • 0
この回答へのお礼

ありがとうございました。equals(Object) を改良する必要があります、というのは予想外でした。
以下の関数を追加して実装したら、myclass 同士の比較はうまくいくようになりました。

publicboolean 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);
}

お礼日時:2009/01/20 16:18

NO1です。



>Integer.equals(Vector配列の(k)番目)、つまりindexOfの引数.equals(Vector配列のelementAt(k))という判断をしている、という理解でよろしいでしょうか。
そうですね。つまりこの場合はObjectのequalsメソッドで判定しているってことです。

>それにしても、こちらでも(同じクラスを使っていても)-1が返されるのがわかりません。
これについてはすでにNo2さんが回答している通り、メソッド(equals(Object))のオーバライドが足らないだけです。
ただ、equalsメソッドは完全一致だとほとんどの人は思うと思いますが、myclassだとフラグ分けしているので完全一致でなくても良いように見えますが、いいんですかね?
ま、これは仕様の話ですか。
    • good
    • 0
この回答へのお礼

なるほど、ということはIntegerで渡してしまうと
myClassをオーバライドしても無駄、ということになりますね。
別のやり方を考えます。

>equalsメソッドは完全一致だと・・・
ええ、確かに普通は完全一致なのですが。こういうことを実現したくていろいろやっている最中でして。
1.表裏が区別できるカードに数字が書いてあります。
2.山札のカードは表裏ごっちゃになっている状態です。
3.表向きのカードが指示されたときには、山札から、「表向きになっていて表面に書いてある数字が一致する」カード(裏はどうでもよい)を、裏向きのカードが指示されたときには、山札から、「裏向きになっていて裏面に書いてある数字が一致する」カード(表はどうでもよい)を、探します。

#フラグの比較もつけてみたけれど思ったとおりには動かない^^;

お礼日時:2009/01/20 16:58

すいません。

前回の回答に一部間違いがありました。
コレクション内部で 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));
    • good
    • 0
この回答へのお礼

ありがとうございます。こちらも、無事、動きました。

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

public boolean equals(Object obj) {
でした。

お礼日時:2009/01/21 09:50

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!