【问题标题】:Java: Retrieving object from the set just by computing its hashcodeJava:仅通过计算其哈希码从集合中检索对象
【发布时间】:2011-07-01 08:31:01
【问题描述】:

我已经创建了 Event 类。如您所见,hashCode 和 equals 方法都只使用 long 类型的 id 字段。

public class Event {
private long id;
private Map<String, Integer> terms2frequency;
private float vectorLength;

@Override
public long hashCode() {
    return this.id;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Event other = (Event) obj;
    if (id != other.id)
        return false;
    return true;
}

我会将这个类的对象存储在 HashSet 集合中。

Set<Event> events = new HashSet<Event>();

由于只有 long 类型的字段用于散列计算,我想通过计算 id 的散列从事件散列集中检索元素。例如:

events.get(3);

是否有可能或者我应该使用 hashMap:

Map<Long, Event> id2event = new HashMap<Long, Event>();

?

【问题讨论】:

  • 有很多奇怪的事情:getClass() != obj.getClass(),但你转换为SimpleEvent而不是EventFloat.floatToIntBits() 上的 long 也很奇怪。 hashCode 公式也没有多大意义(只是加 31?)
  • 使用if (Float.floatToIntBits(id) != Float.floatToIntBits(other.id))if (id != other.id)不一样吗?
  • @Thomas Mueller 正确的评论。这是由于类的先前名称和其中变量的类型而发生的。我在更改类名和变量类型时没有注意到。

标签: java hash hashset


【解决方案1】:

您应该绝对不依赖哈希码的唯一性。 long 有 264 个可能的值; int 只有 232。因此哈希冲突是完全可能的。 不要将哈希码用作唯一的相等性测试。这不是他们的设计目的。

哈希码旨在快速从一个键获得一组潜在匹配,然后通过正常相等性对其进行更严格的检查。

(顺便说一句,我认为使用floatToIntBits 来计算哈希码并不是一个好主意。看看Long.hashCode() 做了什么。)

编辑:当然,即使您确实想依赖它,HashSet&lt;E&gt; 也不会公开通过哈希码获取元素的方法,正是因为这是一个非常糟糕的主意在几乎所有情况下...如果您想要映射,请创建一个Map...

【讨论】:

  • 有没有这种方法可以接受的情况,只是好奇,谢谢
  • @ultrajohn: 如果你可以保证绝对不会发生冲突,那么至少会正确——但仍然不是一个好想法,海事组织。 (当然,无论如何你都不能使用HashSet。)
  • 没有。 Set 存储对象,并且不允许您通过键获取对象。这就是地图的作用。
  • @Jon,Java 中的所有基于哈希的映射,除了(哈希表)确实会扰乱位以“改进”哈希,因此独特的东西并不重要。 floatToIntBits 没问题(这就是 java.lang.Float 的含义,iirc)。由于浮点数是 32 位,因此您无法获得更好的通用哈希值(它们的可能值也少于 2^32)。 HashMap 的额外哈希看起来像 h ^= (h &gt;&gt;&gt; 20) ^ (h &gt;&gt;&gt; 12); return h ^ (h &gt;&gt;&gt; 7) ^ (h &gt;&gt;&gt; 4); 由于 pow2 大小的 buket 需要额外的哈希(否则与标准哈希有太多冲突)
  • @Jon Skeet 感谢您的全面回答。在此,我要感谢所有其他回答我问题的人。我将使用 HashMap。
【解决方案2】:

你可以生成一个静态类(例如:Utility),并创建一个可以在其中生成唯一哈希的方法。但是你必须估计可能会创建多少个对象,然后创建一个算法来生成区分对象的唯一性。而且 Event 类的 hashcode 方法也应该被覆盖,因为你覆盖了 equals 方法。

并使用地图:

Map id2event = new HashMap();

【讨论】:

    猜你喜欢
    • 2014-07-29
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2011-02-26
    • 1970-01-01
    相关资源
    最近更新 更多