集合如何区分对象

How do sets differentiate between objects?

本文关键字:对象 何区 集合      更新时间:2023-10-16

一个集合如何区分Java和C++中的对象?还是集合根本不区分它们?

以这些为例:
C++

std::set<A> aset;
A a(1, 2); // Assume A has only two elements, and this constructor sets them both
aset.insert(a);
A a2(1, 2); // This would initialise a `A' object to the same values as `a', but a different object
aset.count(a2); // Would this return 1 or 0?

Java

set<A> aset;
A a = new A(1, 2); // Assume A has only two elements, and this constructor sets them both
aset.add(a);
A a2 = new A(1, 2); // This would initialise a `A' object to the same values as `a', but a different object
aset.contains(a2); // Would this return true or false?

在C++中,集合依赖于运算符<()是为类A定义的,或者您提供了一个为集合提供严格弱排序的比较对象。

对于Java,它取决于equals, hashcode合同。

对于Java部分,负责确定两个物体是否相等的方法是:

public boolean equals(Object other)

不要与混淆

public int hashCode()

其合约规定两个相等的对象必须返回相同的数字,但返回相同数字的两个对象可能相等,但不一定相等。

equals方法的默认实现是按内存地址相等,因此,如果类A没有重写equals方法,则contains方法将返回false。

若要使set.contents(a2)方法返回true,您必须重写equals和hashCode方法以符合以下要求:

public boolean equals(Object other) {
  return other instanceof A && ((A) other).elem1 = this.elem1 && ((A) other).elem2 =    this.elem2; 
}
public int hashCode() {
    return elem1 * 31 + elem2;
}

集合需要hashCode(假设您使用的是HashSet)来标识对象在集合内部表示中的位置(即在哪里查找对象)。如果您感兴趣,请搜索HashSet\HashMap以了解内部表示。

至于C++部分,如果我记得正确,这取决于正确的运算符重载,但我的C++充其量是生疏的。

编辑:我注意到你特别询问了布景,所以我将详细说明如何:虽然equals方法决定了两个对象之间的相等性,但所使用的集合实现中的一些初步步骤(例如HashSet或TreeSet)可能会依赖于其他东西:

例如,HashSet使用hashCode()函数来查找项可能所在的内部位置,因此,如果A没有重写/正确实现hashCode(。

为了让TreeSet内部实现正确地找到其中的项,所包含的项必须正确地实现Comparable接口,或者TreeSet本身必须提供正确实现的Comparator实例。

对于C++,根据集合::插入C++引用

由于集合容器不允许重复值每个的插入操作检查插入的元素是否为另一个元素已存在于具有相同值的容器,如果是,元素未插入,并且-如果该函数返回一个值迭代器返回

它们检查值,不像Java那样只检查地址。

至少在Java中,比较是在哈希代码上进行的,默认情况下,哈希代码是从对象在内存中的位置创建的。因此,在问题的Java部分,aset.contains(a2);将返回false,因为a2指向与a不同的内存部分。

恐怕我不能评论C++是如何工作的!

Java调用对象的equals方法,如果您没有重写它,那么它与调用Object.hashCode()相同。