4

次のことができるように、オブジェクトのより深い文字列チェックを行いたいと思います。

List<MyObj> myList = new ArrayList<MyObj>() {{
    add(new MyObj("hello"));
    add(new MyObj("world"));
}};

System.out.println(myList.contains("hello")); // true
System.out.println(myList.contains("foo")); // false
System.out.println(myList.contains("world")); // true

しかし、次の完全なコードを使用して、それぞれで false になります

/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
    public static class MyObj {
        private String str;
        private int hashCode;

        public MyObj(String str) {
            this.str = str;
        }

        public @Override boolean equals(Object obj) {
            System.out.println("MyObj.equals(Object)");
            if (obj == this) {
                return true;
            }

            if (obj instanceof String) {
                String strObj = (String) obj;
                return strObj.equals(str);
            }

            return false;
        }

        public @Override int hashCode() {
            if (hashCode == 0) {
                hashCode = 7;
                for (int i = 0; i < str.length(); ++i) {
                    hashCode = hashCode * 31 + str.charAt(i);
                }
            }

            return hashCode;
        }
    }

    public static final MyObj obj1 = new MyObj("hello");
    public static final MyObj obj2 = new MyObj("world");
    public static void main (String[] args) throws java.lang.Exception {
        List<MyObj> myList = new ArrayList<MyObj>() {{
            add(obj1);
            add(obj2);
        }};

        System.out.println(myList.contains("hello"));
        System.out.println(myList.contains("foo"));
        System.out.println(myList.contains("world"));
    }
}

私が正しければ、リストオブジェクトは含まれているオブジェクトを使用equals()hashCode()て評価する必要があります。だから私は@Override彼らと彼らの文字列をさらにチェックします。equals()しかし、出力がないため、決して入りませんMyObj.equals(Object)

4

6 に答える 6

7

java.util.ArrayList#indexOfの ArrayList で内部的に使用されcontains()ます。

チェックがあり、

o.equals(elementData[i])

したがって、文字列とオブジェクトの比較が行わString.equals()れるため、同等性のチェックのために呼び出されます。

于 2013-10-18T13:46:14.467 に答える
5

あなたはequals契約をまったく履行していません:

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

  • これは再帰的です: null 以外の参照値 x に対して、x.equals(x) は true を返す必要があります。あなたのものは再帰的ではありません
  • これは対称的です: null 以外の参照値 x と y の場合、y.equals(x) が true を返す場合に限り、x.equals(y) は true を返す必要があります。あなたのものは対称ではありません。
  • これは推移的です: null 以外の参照値 x、y、および z に対して、x.equals(y) が true を返し、y.equals(z) が true を返す場合、x.equals(z) は true を返す必要があります。あなたのものは推移的ではありません
  • 一貫性があります。null 以外の参照値 x および y に対して、x.equals(y) の複数の呼び出しは一貫して true を返すか、一貫して false を返します。ただし、オブジェクトの equals 比較で使用される情報が変更されていない場合に限ります。
  • null 以外の参照値 x の場合、x.equals(null) は false を返す必要があります。

したがって、メソッドの契約を尊重しないと、意図した動作を期待できません。

たとえば、 equals が ArrayList に含まれるオブジェクトで呼び出され、他の方法では呼び出されないことを保証するものは何ですか"hello".equals(new MyObj("hello"))。それについての保証はありませんが、equals通常は対称であると想定されているため、気にする必要はありません。

于 2013-10-18T13:46:03.333 に答える
1

他の人が指摘したように、問題はequalsメソッドが呼び出されないことです。を呼び出すmyList.contains("hello")と、ArrayListは かどうかをチェックします"hello".equals(<MyObj>)。その逆ではありません。

代わりに、equalsメソッドを適切に実装して、等しい 2 つのMyObjectインスタンスが等しいvalueと見なされるようにし、次のようなヘルパー メソッドを作成することをお勧めします。

public boolean myContains(List<MyObj> list, String value) {
    return list.contains(new MyObj(value));
}
于 2013-10-18T13:57:15.630 に答える
0

リストに aStringと aを比較するように求めていMyObjます...それらは決して「等しい」ことはありません。代わりにマップを試してください:

Map<String, MyObj> map = new HashMap<String, MyObj>() {{
    put("hello", new MyObj("hello"));
    put("world", new MyObj("world"));
}};

次に、次を使用できます。

if (map.containsKey("hello"))

対応するオブジェクトを取得するには:

MyObj o = map.get("hello"); // get() returns null if key not found
于 2013-10-18T13:52:38.817 に答える
0

これは、実行時に呼び出されるオブジェクトと同等ではありませんが、String クラスのものです。また、String の実装は、クラスが String であるかどうかを instanceof でチェックし、String のような操作を実行して答えを決定します。オブジェクトが文字列でない場合は false を返します。

于 2013-10-18T15:27:18.430 に答える
0
List<MyObj> myList = new ArrayList<MyObj>()

のリストなので、チェック中MyObjに使用する必要があります:MyObjmyList.contains

System.out.println(myList.contains(new MyObj("hello")));
System.out.println(myList.contains(new MyObj("foo")));
System.out.println(myList.contains(new MyObj("world")));
于 2013-10-18T13:48:11.443 に答える