简体   繁体   English

Java哈希对象

[英]java hashing objects

I'd like to be able to determine whether I've encountered an object before - I have a graph implementation and I want to see if I've created a cycle, probably by iterating through the Node objects with a tortoise/hare floyd algorithm. 我希望能够确定之前是否遇到过对象-我有一个图形实现,并且想查看是否创建了一个循环,可能是通过使用乌龟/野兔floyd算法遍历Node对象。

But I want to avoid a linear search through my list of "seen" nodes each time. 但是我想避免每次都在我的“可见”节点列表中进行线性搜索。 This would be great if I had a hash table for just keys. 如果我只有键的哈希表,那就太好了。 Can I somehow hash an object? 我可以以某种方式哈希对象吗? Aren't java objects just references to places in memory anyway? Java对象不是只引用内存中的位置吗? I wonder how much of a problem collisions would be if so.. 我想知道如果发生冲突,会有多少问题。

The simple answer is to create a HashSet and add each node to the set the first time you encounter it. 简单的答案是创建一个HashSet并在第一次遇到它时将每个节点添加到该集合中。

The only case that this won't work is if you've overloaded hashCode() and equals(Object) for the node class to implement equality based on node contents (or whatever). 唯一不起作用的情况是,如果您为节点类重载了hashCode()equals(Object)以实现基于节点内容(或其他内容)的相等性。 Then you'll need to: 然后,您需要:

  • use the IdentityHashMap class which uses == and System.identityHashcode rather than equals(Object) and hashCode() , or 使用IdentityHashMap类,该类使用==System.identityHashcode而不是equals(Object)hashCode() ,或者
  • build a hashtable yourself using your own flavour of object identity. 使用您自己的对象标识样式自己构建一个哈希表。

Aren't java objects just references to places in memory anyway? Java对象不是只引用内存中的位置吗?

Yes and no. 是的,没有。 Yes, the reference is represented by a memory address (on most JVMs). 是的,引用由内存地址表示(在大多数JVM上)。 The problem is that 1) you can't get hold of the address, and 2) it can change when the GC relocates the object. 问题在于1)您无法获得该地址,并且2)当GC重新定位该对象时,它可以更改。 This means that you can't use the object address as a hashcode. 这意味着您不能将对象地址用作哈希码。

The identityHashCode method deals this by returning a value that is initially based on the memory address. identityHashCode方法通过返回最初基于内存地址的值来解决此问题。 If you then call identityHashCode again for the same object, you are guaranteed to get the same value as before ... even if the object has been relocated. 如果随后再为同一对象调用identityHashCode ,则即使对象已重定位,也可以确保获得与以前相同的值。

I wonder how much of a problem collisions would be if so.. 我想知道如果发生冲突,会有多少问题。

The hash values produced by the identityHashCode method can collide. identityHashCode方法产生的哈希值可能会发生冲突。 (That is, two distinct objects can have the same identity hashcode value.) Anything that uses these values has to deal with this. (也就是说,两个不同的对象可以具有相同的标识哈希码值。)使用这些值的任何事物都必须对此进行处理。 (The standard HashSet and IdentityHashMap classes take care of these collisions ... if you chose to use them.) (标准的HashSetIdentityHashMap类可以解决这些冲突……如果您选择使用它们。)

I'd like to be able to determine whether I've encountered an object before 我希望能够确定之前是否遇到过物体

Use an IdentityHashMap . 使用IdentityHashMap It is the ideal for your job since it is not an equals but a == implementation. 这是您的工作的理想选择,因为它不是equals而是==实现。

Take a look at HashSet . 看看HashSet Note that in order for objects to work with HashSet, they need to provide correct implementations of hashCode and equals methods of the java.lang.Object class. 请注意,为了使对象与HashSet一起使用,它们需要提供hashCode正确实现以及java.lang.Object类的equals方法。

You'll need to implement a hash function for your objects. 您需要为您的对象实现一个哈希函数。 This is done by overriding hashCode() defined in java.lang.Object . 这是通过覆盖java.lang.Object定义的hashCode()来完成的。 This method is used by HashMap , HashSet etc to store objects. HashMapHashSet等用于存储对象。 In hashCode() it's up to you to calculate a hash for the object. hashCode() ,由您来计算对象的哈希值。 Don't forget to also implement the equals() -method! 别忘了还要实现equals() -方法!

Take a look at Java collection framework (http://docs.oracle.com/javase/tutorial/collections/) 看一下Java收集框架(http://docs.oracle.com/javase/tutorial/collections/)

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

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