假设我创建了一个对象并将其添加到数组列表中。如果我然后用完全相同的构造函数输入创建另一个对象,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;
    }
}

这是类应该如何实现有contains()返回true吗?


当前回答

我认为正确的实现应该是

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;
    }
}

其他回答

记录重写等于

你说:

另一个具有完全相同构造函数输入的对象

还有……

假设构造函数没有对输入做任何奇怪的事情,并且存储在两个对象中的变量是相同的。

正如其他答案解释的那样,您必须重写object# equals方法,以便list# contains工作。

在Java 16+中,记录功能会自动为您覆盖该方法。

记录是编写类的一种简单方式,其主要目的是透明且不变地传递数据。默认情况下,只需声明成员字段。编译器隐式创建构造函数、getter、equals & hashCode和toString。

默认情况下,等号逻辑是将一个对象的每个成员字段与同一类的另一个对象中的对应项进行比较。同样,hashCode和toString方法的默认实现也考虑每个成员字段。

record Thing( int amount ) {} ;

就是这样,这就是一个功能完整的只读类所需的所有代码,不需要任何常见的样板代码。

使用例子。

Thing x = new Thing( 100 ) ; 
Thing y = new Thing( 100 ) ; 
boolean parity = x.equals( y ) ;

运行时。

奇偶校验= true

回到你的列表#包含问题。

Thing x = new Thing( 100 );
List < Thing > things =
        List.of(
                new Thing( 100 ) ,
                new Thing( 200 ) ,
                new Thing( 300 )
        );

boolean foundX = things.contains( x );

运行时。

foundX = true


附加特性:可以在方法中本地声明一条记录。或者像传统的类一样,可以将记录声明为嵌套类或单独的类。

ArrayList使用在类(你的case Thing类)中实现的equals方法来进行相等比较。

Generally you should also override hashCode() each time you override equals(), even if just for the performance boost. HashCode() decides which 'bucket' your object gets sorted into when doing a comparison, so any two objects which equal() evaluates to true should return the same hashCode value(). I cannot remember the default behavior of hashCode() (if it returns 0 then your code should work but slowly, but if it returns the address then your code will fail). I do remember a bunch of times when my code failed because I forgot to override hashCode() though. :)

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

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;
    }
}

现在它工作了;)