ArrayList的contains()方法如何评估对象?


303

假设我创建一个对象并将其添加到我的对象中ArrayList。如果我然后使用完全相同的构造函数输入创建另一个对象,则该contains()方法将两个对象评估为相同吗?假设构造函数对输入没有任何有趣的事情,并且存储在两个对象中的变量相同。

ArrayList<Thing> basket = new ArrayList<Thing>();  
Thing thing = new Thing(100);  
basket.add(thing);  
Thing another = new Thing(100);  
basket.contains(another); // true or false?

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

请问该如何class实现contains()退货true

Answers:


339

ArrayList implements列表接口。

如果您在Javadoc中查找Listcontains方法,则会看到它使用该equals()方法来评估两个对象是否相同。


61
万一您打算重写equals(),请确保还重写hashcode()方法。如果您不愿意,在使用“收藏夹”时事情可能无法按预期运行?
Mohd Farid

34
这是正确的答案,但请注意,您需要更改equals方法以接受Object而不是Thing。如果您不这样做,将不会使用equals方法。:)
mdierker

1
刚刚为我自己发现,eclipse在“源”菜单下具有“ Generate hashCode()and equals”。
Volodymyr Krupach '16

这将回答标题中的问题,而不是描述中的问题,即“如果我随后使用完全相同的构造函数输入创建另一个对象,contains()方法将两个对象的值视为相同吗?”
robguinness

3
Collections以一种优化的方式来完成他们的工作,这意味着contains()首先检查hashCode两个对象的s,然后再调用equals()。如果hashCodes不同(对于的两个不同的实例总是如此Thing),equals()则不会调用该方法。根据经验,当您覆盖时equals(),您不应忘记也要覆盖hashCode()
Sevastyan Savanyuk

52

我认为正确的实现应该是

public class Thing
{
    public int value;  

    public Thing (int x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

1
if声明是不必要的。instanceof足够。
保罗

@Paul您要说的是陈述的哪一部分?
ChristopheCVB

4
object != null条件是不必要的,因为也object instanceof Thing检查对象也不为null。
亚历山大·法伯

15

ArrayList使用在类(您的案例Thing类)中实现的equals方法进行相等比较。


12

通常,即使只是为了提高性能,hashCode()每次覆盖时也应覆盖equals()HashCode()决定进行比较时将对象分类到哪个“存储桶”,因此任何两个equal()评估为true的对象都应返回相同的hashCode value()。我不记得默认行为hashCode()(如果返回0,则您的代码应该可以运行,但是运行缓慢,但是如果返回地址,则代码将失败)。我确实记得我的代码失败过很多次,因为我忘记重写hashCode()了。:)


7

它在对象上使用equals方法。因此,除非Thing重写equals并使用对象中存储的变量进行比较,否则该contains()方法将不会返回true 。


6
class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

您必须写:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

现在可以了;)


6
您不应该做Thing x =(Thing)o; 无需先检查其他对象是否为空
steelshark

5

只是要注意,当value不是原始类型时,以下实现是错误的:

public class Thing
{
    public Object value;  

    public Thing (Object x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

在这种情况下,我提出以下建议:

public class Thing {
    public Object value;  

    public Thing (Object x) {
        value = x;
    }

    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Thing) {
            Thing thing = (Thing) object;
            if (value == null) {
                return (thing.value == null);
            }
            else {
                return value.equals(thing.value);
            }
        }

        return false;
    }
}

在消除重复的同时如何实现呢?
Sujay

4

其他张贴者解决了关于contains()如何工作的问题。

您的问题的另一个重要方面是如何正确实现equals()。答案实际上取决于此特定类的对象相等性。在您提供的示例中,如果您有两个都x = 5的不同对象,它们是否相等?这实际上取决于您要执行的操作。

如果只对对象相等感兴趣,则.equals()(对象提供的那个)的默认实现仅使用标识(即this == other)。如果那是您想要的,那就不要在类上实现equals()(让它继承自Object)。您编写的代码虽然对于身份验证来说是正确的,但它永远不会出现在真实的类b / c中,与使用默认的Object.equals()实现相比,它没有任何好处。

如果您只是开始使用这些东西,我强烈推荐Joshua Bloch撰写的Effective Java一书。这是一本很好的书,涵盖了这种事情(以及当您尝试做比基于身份的比较更多的事情时,如何正确实现equals())


出于我的目的,我试图查看ArrayList中是否有一个相等值的对象。我想这是一种黑客。感谢您的图书推荐
Mantas Vidutis 2010年

3

JavaDoc的快捷方式:

布尔 contains(Object o)

如果此列表包含指定的元素,则返回true。更正式地讲,当且仅当此列表包含至少一个元素e使得(o == null?e == null:o.equals(e))时,返回true。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.