我希望能够确定我之前是否遇到过一个对象 - 我有一个图形实现,我想看看我是否已经创建了一个循环,可能是通过使用乌龟迭代Node对象/野兔弗洛伊德算法。
但我希望每次都避免通过我的“看到”节点列表进行线性搜索。如果我只有键的哈希表,这将是很好的。我可以以某种方式哈希一个对象吗?难道java对象只是引用内存中的位置吗?我想知道如果碰撞会有多少问题......
答案 0 :(得分:5)
简单的答案是创建一个HashSet
并在第一次遇到它时将每个节点添加到集合中。
唯一不起作用的情况是,如果您为节点类重载hashCode()
和equals(Object)
以基于节点内容(或其他)实现相等性。然后你需要:
IdentityHashMap
类使用==
和System.identityHashcode
而不是equals(Object)
和hashCode()
,或java对象是不是只引用了内存中的位置?
是和否。是的,引用由内存地址表示(在大多数JVM上)。问题是1)你无法掌握地址,2)当GC重新定位对象时它可以改变。这意味着您不能将对象地址用作哈希码。
identityHashCode
方法通过根据内存地址返回最初的值来解决此问题。如果您再次为同一个对象调用identityHashCode
,则可以保证获得与之前相同的值...即使该对象已被重新定位。
我想知道如果碰撞会出现多少问题......
identityHashCode
方法生成的哈希值可能会发生冲突。 (也就是说,两个不同的对象可以具有相同的标识哈希码值。)任何使用这些值的东西都必须处理这个问题。 (标准HashSet
和IdentityHashMap
类负责处理这些冲突......如果您选择使用它们。)
答案 1 :(得分:4)
我希望能够确定我是否遇到了一个物体 前
使用IdentityHashMap。这是您工作的理想选择,因为它不是equals
,而是==
实施。
答案 2 :(得分:2)
看看HashSet。请注意,为了使对象能够与HashSet一起使用,他们需要提供hashCode
类的equals
和java.lang.Object
方法的正确实现。
答案 3 :(得分:1)
您需要为对象实现哈希函数。这是通过覆盖hashCode()
中定义的java.lang.Object
来完成的。 HashMap
,HashSet
等使用此方法来存储对象。在hashCode()
中,由您来计算对象的哈希值。不要忘记同时实施equals()
- 方法!
查看Java集合框架(http://docs.oracle.com/javase/tutorial/collections/)