web-dev-qa-db-ja.com

.Contains()メソッドがオーバーライドされたequalsメソッドを呼び出さない

FooオブジェクトのArrayListを作成し、equalsメソッドをオーバーライドして、equalsメソッドを呼び出すためのcontainsメソッドを取得できないという問題があります。 equalsとhashcodeを一緒にオーバーライドしようとしましたが、まだ機能しません。私はこれがなぜなのか論理的な説明があると確信していますが、現時点では自分でそれを理解することはできません。リストに指定されたIDが含まれているかどうかを確認する方法が必要です。

コードは次のとおりです。

import Java.util.ArrayList;
import Java.util.List;

public class Foo {

    private String id;


    public static void main(String... args){
        Foo a = new Foo("ID1");
        Foo b = new Foo("ID2");
        Foo c = new Foo("ID3");
        List<Foo> fooList = new ArrayList<Foo>();
        fooList.add(a);
        fooList.add(b);
        fooList.add(c);
        System.out.println(fooList.contains("ID1"));
        System.out.println(fooList.contains("ID2"));
        System.out.println(fooList.contains("ID5"));
    }   

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

    @Override
    public boolean equals(Object o){
        if(o instanceof String){
            String toCompare = (String) o;
            return id.equals(toCompare);
        }
        return false;
    }



    @Override
    public int hashCode(){
        return 1;
    }
}

出力:false false false

26
Reid Mac

これは、equals()symmetricではないためです:

_new Foo("ID1").equals("ID1");
_

だが

_"ID1".equals(new Foo("ID1"));
_

真実ではない。これは equals() 契約に違反しています:

Equalsメソッドは、null以外のオブジェクト参照で等価関係を実装します。

  • [...]

  • symmetric:null以外の参照値xおよびyの場合、x.equals(y)はtrueのみを返す必要がありますy.equals(x)trueを返す場合。

reflexiveでもありません:

  • reflexive:null以外の参照値xの場合、x.equals(x)はtrueを返す必要があります。
_Foo foo = new Foo("ID1");
foo.equals(foo)  //false!
_

@ mbockusequals()の正しい実装を提供します:

_public boolean equals(Object o){
  if(o instanceof Foo){
    Foo toCompare = (Foo) o;
    return this.id.equals(toCompare.id);
  }
  return false;
}
_

ただし、Fooのインスタンスをcontains()に渡す必要があります。

_System.out.println(fooList.contains(new Foo("ID1")));
System.out.println(fooList.contains(new Foo("ID2")));
System.out.println(fooList.contains(new Foo("ID5")));
_

最後に、hashCode()を実装して、一貫した結果を提供する必要があります(2つのオブジェクトがequalである場合、等しいhashCode()でなければなりません):

_@Override
public int hashCode() {
    return id.hashCode();
}
_
44

Equalsメソッドを変更するとともに、hashCode()関数をオーバーライドする必要があります。現在、Fooオブジェクトを確認する必要がある場合、比較するオブジェクトがStringのインスタンスであるかどうかを確認しています。

public boolean equals(Object o){
    if(o instanceof Foo){
        Foo toCompare = (Foo) o;
        return this.id.equals(toCompare.id);
    }
    return false;
}

Eclipseを使用している場合は、ソース-> Generate hashcode()and equals()...に移動して、EclipseにhashCodeとequalsを生成させることをお勧めします...

11
Mike Bockus

HashCodeを実装する必要があります

@Override
public int hashCode() {
    return id.hashCode();
}

containsがなくてもArrayListで機能しますが。あなたの大きな問題は、equalsがFooオブジェクトではなくStringを期待していること、そしてStringsを含むように要求することです。実装がリスト内の各イジェクトを送信する文字列と等しいかどうかを尋ねた場合、コードは動作しますが、実装は文字列に対して、もちろんそれがFooオブジェクトと等しいかどうかを尋ねます。

等しいを使用

@Override
public boolean equals(Object o){
    if(o instanceof Foo){
        String toCompare = ((Foo) o).id;
        return id.equals(toCompare);
    }
    return false;
}

そして、チェックが含まれています

System.out.println(fooList.contains(new Foo("ID1")));
5
Roger Lindsjö