Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ArrayList未使用重写的equals_Java_Arraylist_Overriding_Equals - Fatal编程技术网

Java ArrayList未使用重写的equals

Java ArrayList未使用重写的equals,java,arraylist,overriding,equals,Java,Arraylist,Overriding,Equals,我在获取ArrayList以正确使用重写的equals时遇到问题。问题是,我试图对单个键字段使用equals to only测试,并使用ArrayList.contains()测试是否存在具有正确字段的对象。这里有一个例子 public class TestClass { private static class InnerClass{ private final String testKey; //data and such InnerClass(S

我在获取ArrayList以正确使用重写的equals时遇到问题。问题是,我试图对单个键字段使用equals to only测试,并使用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")); 
    }    
}
公共类TestClass{
私有静态类内部类{
私有最终字符串testKey;
//数据等
InnerClass(字符串testKey,int-dataStuff){
this.testKey=testKey;
//等
}
@凌驾
公共布尔等于(中的对象){
System.out.println(“到达此处”);
if(in==null){
返回false;
}else if(在instanceof字符串中){
字符串inString=(字符串)in;
返回testKey==null?false:testKey.equals(inString);
}否则{
返回false;
}       
}       
}
公共静态void main(字符串[]args){
ArrayList objectList=新建ArrayList();
//添加一些条目
add(新的内部类(“惟一ID1”,42));
System.out.println(objectList.contains(“惟一ID1”);
}    
}
让我担心的是,我不仅在输出上出错,而且没有得到“到达此处”的输出

有人知道为什么这个覆盖被完全忽略了吗?覆盖和内部类是否有一些我不知道的微妙之处

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

虽然没有回答你的问题,但许多收藏都使用了
hashcode()
。您也应该覆盖它,以便“同意”使用
equals()

实际上,您应该始终同时实现
equals
hashcode
,并且它们应该始终保持一致。正如
Object.equals()
的javadoc所述:

请注意,通常有必要 无论何时重写hashCode方法 此方法被重写,以便 维护项目的总合同 hashCode方法,该方法声明 相等的对象必须具有相等的哈希 代码


具体地说,许多集合依赖于支持此契约-否则行为未定义。

您正在调用的
包含
,其参数是
字符串,而不是
内部类

System.out.println( objectList.contains("UNIQUE ID1"))
在我的JDK中:

public class ArrayList {

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

    public int indexOf(Object o) {
    if (o == null) {
        // omitted for brevity - aix
    } else {
        for (int i = 0; i < size; i++)
        if (o.equals(elementData[i])) // <<<<<<<<<<<<<<<<<<<<<<
            return i;
    }
    return -1;
    }
}
公共类数组列表{
公共布尔包含(对象o){
返回索引of(o)>=0;
}
public int indexOf(对象o){
如果(o==null){
//为简洁起见省略-aix
}否则{
对于(int i=0;i如果(o.equals(elementData[i])/检查
ArrayList
的源,您将看到它调用其他对象的
equals
。在您的情况下,它将调用
字符串的
equals
“UNIQUE ID1”
,这将检查其他对象的类型是否为
字符串
,并且只返回
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;
}
不要忘记为只比较
id
内部类实现
equals

根据,它被定义为返回
true

当且仅当此列表包含至少一个元素
e
,从而
(o==null?e==null:o.equals(e))

请注意,此定义在
o
上调用
equals
,它是参数,而不是
列表中的元素

因此将调用
String.equals()
,而不是
InnerClass.equals()

还要注意的是

它是对称的:对于任何非空参考值
x
y
x.equals(y)
应返回
true
当且仅当
y.equals(x)
返回
true

但是您违反了这个约束,因为
newtestclass(“foo”,1).equals(“foo”)
返回
true
“foo”。equals(newtestclass(“foo”,1))
将始终返回
false

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


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

通常,您还需要覆盖
hashCode()
但这不是这里的主要问题。您有一个不对称的
equals(…)
方法。文档明确指出它应该是对称的:

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

你所观察到的是由于合同破裂而导致的意外行为

创建一个实用程序方法,该方法迭代所有项,并在字符串上使用
equals(..)
进行验证:

public static boolean containsString(List<InnerClass> items, String str) {
    for (InnerClass item : items) {
        if (item.getTestKey().equals(str)) {
           return true;
        }
    }
    return false;
} 

equals实现错误。in参数不应该是
字符串
。它应该是
内部类

public boolean equals(Object o) {
  if (this == o) return true;
  if (!(o instanceof InnerClass) return false;
  InnerClass that = (InnerClass)o;
  // check for null keys if you need to
  return this.testKey.equals(that.testKey);
}
(请注意,
instanceof null
返回false,因此不需要先检查null)

然后,您将使用以下方法测试列表中是否存在等效对象:

objectList.contains(new InnerClass("UNIQUE ID1"));

但是,如果您真的想通过字符串键检查InnerClass,为什么不使用
Map
来代替呢?

您的代码有一些问题。我的建议是,如果您不熟悉它,就避免完全覆盖equals,并将其扩展到一个新的实现中,就像这样

class MyCustomArrayList extends ArrayList<InnerClass>{

    public boolean containsString(String value){
        for(InnerClass item : this){
            if (item.getString().equals(value){
                return true;
            }
        }
        return false;
    }

}
我建议这样做是因为如果你覆盖了equals,那么它也应该覆盖hashCode,而且你似乎缺乏一点关于hashCode的知识
objectList.contains(new InnerClass("UNIQUE ID1"));
class MyCustomArrayList extends ArrayList<InnerClass>{

    public boolean containsString(String value){
        for(InnerClass item : this){
            if (item.getString().equals(value){
                return true;
            }
        }
        return false;
    }

}
List myList = new MyCustomArrayList()
myList.containsString("some string");
package com.test;

import java.util.ArrayList;    
import java.util.List;

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 in1) {
            System.out.println("reached here");
            if(in1 == null) {
                return false;
            }else if( in1 instanceof InnerClass) {
                return ((InnerClass) this).testKey == null ? false : ((InnerClass) this).testKey.equals(((InnerClass) in1).testKey);
            }else {
                return false;
            }       
        }       
    }

    public static void main(String[] args) {    
        ArrayList<InnerClass> objectList = new ArrayList<InnerClass>();
        InnerClass in1 = new InnerClass("UNIQUE ID1", 42);
        InnerClass in2 = new InnerClass("UNIQUE ID1", 42);

        //add some entries
        objectList.add(in1);
        System.out.println( objectList.contains(in2)); 
    }    
}
public static InnerClass empty(String testKey) {
    InnerClass in = new InnerClass();
    in.testKey =testKey;
    return in;
}
ind position = list.indexOf(InnerClass.empty(key));
@Override
    public boolean equals (Object in) {
        System.out.println("reached here");
        if(in == null) {
        return false;
        }else if( in instanceof InnerClass) {
        String inString = ((InnerClass)in).testKey;
        return testKey == null ? false : testKey.equals(inString);
        }else {
        return false;
        }       
    }  
System.out.println(objectList.stream().filter(obj -> obj.getTestKey().equals("UNIQUE ID1")).findAny().isPresent());
public String getTestKey() {

   return testKey;
}