问题描述
|
集合如何区分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?
爪哇
set<A> aset;
A a = new A(1,and this constructor sets them both
aset.add(a);
A a2 = new A(1,but a different object
aset.contains(a2); // Would this return true or false?
解决方法
在C ++中,集合取决于为类A定义的operator <(),或者您提供一个比较对象,该对象对集合提供严格的弱排序。
, 对于
Java
,它取决于equals,hashcode
合同。
, 对于Java部分,
确定两个对象是否相等的方法是:
public boolean equals(Object other)
不要与
public int hashCode()
谁的合同规定两个相等的对象必须返回相同的数字,但是两个返回相同数字的对象可以但不一定相等。
equals方法的默认实现是按内存地址进行相等,因此,如果类A没有覆盖equals方法,则contains方法将返回false。
要使set.contains(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方法确定两个对象之间的相等性,但是所使用的set实现中的一些初步步骤(例如HashSet或TreeSet)可能会基于其他一些内容:
例如,HashSet使用hashCode()函数查找该项目可能位于的内部位置,因此如果A没有重写/正确实现hashCode()函数,则set.contains(a2)可能返回true或false(对于默认实现,它是不确定的-取决于内存位置和集合的当前容量)。
为了使TreeSet内部实现能够在其中正确找到项目,所包含的项必须正确实现Comparable接口,或者TreeSet本身必须提供有正确实现的Comparator实例。
, 对于C ++,根据C ++参考中的set :: insert
由于集合容器不允许重复值,因此
每个插入操作检查
元素是否插入
元素已经存在
具有相同值的容器,如果是这样,
没有插入元素,并且-if
该函数返回一个值-
返回它的迭代器
。
它们检查值,与Java不同,Java只检查地址。
, 至少在Java中,对哈希码进行比较,默认情况下,哈希码是根据对象在内存中的位置创建的。因此,在问题的Java部分中,aset.contains(a2);
将返回false,因为a2
指向内存中与a
不同的部分。
恐怕我无法评论C ++的工作方式!
, Java调用对象的equals
方法,如果尚未覆盖它,则与调用Object.hashCode()
相同。