简体   繁体   English

集合如何区分对象?

[英]How do sets differentiate between objects?

How does a set differentiate between objects in both Java and C++?集合如何区分 Java 和 C++ 中的对象? Or do sets not differentiate them at all?还是集合根本不区分它们?

Take these for example:以这些为例:
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 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?

In C++ the set depends on operator<() being defined for the class A, or that you supply a comparison object providing strict weak ordering to the set.在 C++ 中,该集合取决于为 class A 定义的 operator<(),或者您提供比较 object 为集合提供严格的弱排序

For Java it depends on the equals, hashcode contract.对于Java ,它取决于equals, hashcode合约。

For the Java part, The method in charge of determining whether two objects are equal is:对于Java部分,负责判断两个对象是否相等的方法是:

public boolean equals(Object other)

Not to be confused with不要混淆

public int hashCode()

Whose contract states that two equals objects must return the same number, but two objects that returned the same number may be, but are not necessarily, equal.谁的合同规定两个相等的对象必须返回相同的数字,但返回相同数字的两个对象可能但不一定相等。

The default implementation for the equals method is equality by memory address, therefor if class A did not override the equals method the contains method will return false. equals 方法的默认实现是通过 memory 地址相等,因此如果 class A 没有覆盖 equals 方法,则 contains 方法将返回 false。

To have the set.contains(a2) method return true you must override the equals and hashCode method to comply as so:要让 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;
}

The hashCode is required (assuming you're using a HashSet) for the set to identify where in the internal representation of the set the object may be (ie where to look for it).集合需要 hashCode(假设您使用 HashSet)来识别 object 可能在集合的内部表示中的位置(即在哪里寻找它)。 Search for HashSet\HashMap to understand the internal representation if you're interested.如果您有兴趣,请搜索 HashSet\HashMap 以了解内部表示。

As for the C++ part, If I remember correctly it depends on the correct operator overloading, but my C++ is rusty at best.至于 C++ 部分,如果我没记错的话,它取决于正确的运算符重载,但我的 C++ 充其量是生锈的。

EDIT: I noticed you specifically asked about sets so I'll elaborate a bit more on how that: While the equals method is what determines equality between two objects, some preliminary steps in the set implementation used (eg HashSet or TreeSet) might relay on something extra:编辑:我注意到您特别询问了集合,所以我将详细说明如何:虽然 equals 方法确定两个对象之间的相等性,但使用的集合实现中的一些初步步骤(例如 HashSet 或 TreeSet)可能会继续额外的东西:

For example, the HashSet uses the hashCode() function to find the internal location the item might be in, so if A did not override/correctly implement the hashCode() function, the set.contains(a2) may return true or false (for default implementation it's non deterministic - depends on memory location and the current capacity of the set).例如,HashSet 使用 hashCode() function 来查找项目可能所在的内部位置,因此如果 A 没有覆盖/正确实现 hashCode() function,则 set.contains(a2) 可能返回 true 或 false(对于默认实现,它是不确定的 - 取决于 memory 位置和集合的当前容量)。

For a TreeSet internal implementation to correctly find items within it either the items contained must be implement the Comparable interface properly or the TreeSet itself must be supplied with a Comparator instance implemented properly.为了让 TreeSet 内部实现正确地在其中找到项目,所包含的项目必须正确实现 Comparable 接口,或者必须为 TreeSet 本身提供正确实现的 Comparator 实例。

In Java at least, comparison is done on a hash code, which by default is created from the location of the object in memory.至少在 Java 中,比较是在 hash 代码上完成的,默认情况下,该代码是从 objectCD881269B4357106 中的 objectCD881269B4957106 的位置创建的。 So in the Java part of the question, aset.contains(a2);所以在问题的 Java 部分, aset.contains(a2); would return false, as a2 points to a different part of the memory to a .将返回 false,因为a2指向 memory 到a的不同部分。

I'm afraid I can't comment on how C++ works!恐怕我无法评论 C++ 的工作原理!

for C++, according to set::insert in C++ Reference对于 C++,根据 set::insert in C++ 参考

Because set containers do not allow for duplicate values, the insertion operation checks for each element inserted whether another element exists already in the container with the same value, if so, the element is not inserted and -if the function returns a value- an iterator to it is returned因为集合容器不允许重复值,插入操作会检查每个插入的元素是否在容器中已经存在具有相同值的另一个元素,如果是,则不插入该元素并且 - 如果 function 返回值 - 一个迭代器归还给它

. .

They check for the values, unlike Java, which only checks for the address instead.他们检查值,不像 Java,它只检查地址。

Java calls the object's equals method, which, if you haven't overridden it, is the same as calling Object.hashCode() . Java 调用对象的equals方法,如果您没有重写它,则与调用Object.hashCode()相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM