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


当前回答

只是想指出,当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;
    }
}

其他回答

JavaDoc的快捷方式:

boolean contains(对象o)

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

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

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

ArrayList实现了列表接口。

如果查看Javadoc for List中的contains方法,就会发现它使用equals()方法来计算两个对象是否相同。

记录重写等于

你说:

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

还有……

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

正如其他答案解释的那样,您必须重写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


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