ArrayList不使用重写的equals

K.B*_*rad 10 java overriding equals arraylist

我有一个问题,让ArrayList正确使用overriden equals.问题是我正在尝试使用equals来测试单个键字段,并使用ArrayList.contains()来测试是否存在具有正确字段的对象.这是一个例子

public class TestClass  {
    private static class InnerClass{    
    private final String testKey;
    //data and such

    InnerClass(String testKey, int dataStuff) {
        this.testKey =testKey;
        //etc
    }
    @Override
    public boolean equals (Object in) {
        System.out.println("reached here");
        if(in == null) {
        return false;
        }else if( in instanceof String) {
        String inString = (String) in;
        return testKey == null ? false : testKey.equals(inString);
        }else {
        return false;
        }       
    }       
    }

    public static void main(String[] args) {    
    ArrayList<InnerClass> objectList = new ArrayList<InnerClass>();
    //add some entries
    objectList.add(new InnerClass("UNIQUE ID1", 42));
    System.out.println( objectList.contains("UNIQUE ID1")); 
    }    
}
Run Code Online (Sandbox Code Playgroud)

令我担心的是,我不仅在输出上出错,而​​且我也没有得到"达到此处"输出.

有没有人有任何想法为什么这个覆盖被完全忽略?是否有一些微妙的覆盖和内部类我不知道?

编辑:网站有问题所以我似乎无法标记答案.感谢您的快速回复:是的,我认为它是字符串.equals thta被调用,而不是我自定义的.我想现在这是老式的支票

Ser*_*nov 16

如果检查源ArrayList,您将看到它调用equals其他对象.在你的情况下,它会调用equalsString "UNIQUE ID1",这将检查其他对象的类型是不是String和刚刚返回false:

public boolean contains(Object o) {
    return indexOf(o) >= 0;
}

public int indexOf(Object o) {
    ...     
    for (int i = 0; i < size; i++)
    if (o.equals(elementData[i]))
        return i;
    ...
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

为了您的通话的情况下containsInnerClass只包含id:

objectList.contains(new InnerClass("UNIQUE ID1"))
Run Code Online (Sandbox Code Playgroud)

不要忘记实现equalsInnerClass,其比较id而已.


Joa*_*uer 7

根据JavaDoc的List.contains(o)说法,它被定义为返回true

当且仅当此列表包含至少一个e这样的元素时(o==null ? e==null : o.equals(e)).

请注意,此定义调用equalson o,它是参数,不是 in中的元素List.

因此String.equals()将被召唤而不是InnerClass.equals().

还要注意国家的合同Object.equals()

它是对称的:对于任何非空引用值xy,x.equals(y)应该返回true当且仅当y.equals(x)回报true.

但是你违反了这个约束,因为new TestClass("foo", 1).equals("foo")返回true"foo".equals(new TestClass("foo", 1))总会返回false.

不幸的是,这意味着您的用例(可以等于另一个标准类的自定义类)无法以完全符合的方式实现.

如果你仍然想做这样的事情,你必须非常仔细地阅读所有集合类的规范(有时是实现),并检查这样的缺陷.