问题描述
我有此代码:
public class Tray {
private Set<Block> blocks;
private int numColumns;
private int numRows;
//constructor
public Tray (int numRows, int numColumns){
this.numColumns = numColumns;
this.numRows = numRows;
blocks = new HashSet<>();
}
public boolean satisfiesGoal(Tray other){
Block thisBlock = this.blocks.iterator().next();
Block otherBlock = other.blocks.iterator().next();
boolean hashesEqual = thisBlock.hashCode() == otherBlock.hashCode(); // this is true
boolean areEqual = thisBlock.equals(otherBlock) && otherBlock.equals(thisBlock); // this is true
boolean contains = this.blocks.contains(otherBlock); // this is false, why?
return contains;
}
在主要方法中,我将2个块添加到了各自的托盘中.根据调试器,变量"hashesEqual"和"areEqual"为true,但布尔值"contains"为false.关于为什么两个对象的哈希值既相等又根据"equals"方法相等的任何想法,但是在HashSet中不包含equal对象?
In the main method I have added the 2 Blocks to their respective Trays. According to the debugger, the variables "hashesEqual" and "areEqual" are true, but the boolean "contains" is false. Any ideas as to why the hashes of 2 objects would be equal as well as equal according to the "equals" method, but would not contain the equal object in a HashSet?
推荐答案
如果您以影响对象相等性和散列代码的方式修改对象,并在 将它们添加到HashSet之后,就会发生此问题.该集合将发生故障,因为在对应于其新值的哈希表的正确插槽中找不到对象.
This problem happens if you modify the objects in a way that affects their equality and hash codes after adding them to the HashSet. The set will malfunction because the objects are not found in the correct slot of the hash table corresponding to their new value.
同样,如果您修改用作键的对象,则HashMap将发生故障.与TreeSet和TreeMap相似.所有这些数据结构都可以快速定位对象,因为每个对象的值决定了它的存储位置.如果随后修改这些对象,则结构会出错.
Likewise, a HashMap will malfunction if you modify objects used as keys. Similarly with TreeSet and TreeMap. All these data structures can locate objects quickly because each object's value dictates its storage location. The structure becomes wrong if those objects are then modified.
不可变对象最好作为集合元素和映射键,因为它们避免了这种复杂性.
Immutable objects are nicer as set elements and map keys because they avoid this complication.
如果必须修改属于对象相等性的字段,则需要先将其从集合中暂时删除,然后再添加.或者,将列表用作对象的主要容器,并仅在需要时构造一个临时集.
If you must modify fields that are part of an object's equality, you'll need to temporarily remove it from the set first, and add it again afterwards. Or, use a list as the main container for your objects, and construct a temporary set only when needed.
这篇关于HashSet.contains不应返回false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!