Java:通过计算对象的哈希代码从集合中检索对象

Java:通过计算对象的哈希代码从集合中检索对象,java,hash,hashset,Java,Hash,Hashset,我已经创建了事件类。如您所见,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

我已经创建了事件类。如您所见,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;
}
我是否可以或应该使用hashMap来实现它:

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

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

散列码的设计目的是快速地从一个键获取一组潜在的匹配项,然后使用正常的相等性更严格地检查这些匹配项

顺便说一句,我认为使用floatToIntBits来计算开始时的哈希代码不是一个好主意。看看Long.hashCode的作用

编辑:当然,即使你真的想依赖它,HashSet也不会公开一个通过散列代码获取元素的方法,因为这在几乎所有情况下都是一个非常糟糕的主意。。。如果您想要映射,请创建映射…

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

散列码的设计目的是快速地从一个键获取一组潜在的匹配项,然后使用正常的相等性更严格地检查这些匹配项

顺便说一句,我认为使用floatToIntBits来计算开始时的哈希代码不是一个好主意。看看Long.hashCode的作用


编辑:当然,即使你真的想依赖它,HashSet也不会公开一个通过散列代码获取元素的方法,因为这在几乎所有情况下都是一个非常糟糕的主意。。。如果你想要一个映射,创建一个映射…

你可以生成一个静态类,例如:Utility,并创建一个可以在其中生成唯一散列的方法。但是你必须估计在可能的情况下将创建多少个对象,然后创建一个算法来生成唯一的来区分对象。而且,事件类的hashcode方法也应该被覆盖,因为您覆盖了equals方法

并使用地图:


Map id2event=新HashMap

您可以生成一个静态类,例如:Utility,并创建一个可以在其中生成唯一散列的方法。但是您必须估计在可能的情况下将创建多少个对象,然后创建一个算法来生成唯一散列以区分对象。而且,事件类的hashcode方法也应该被覆盖,因为您覆盖了equals方法

并使用地图:


Map id2event=新HashMap

是否有这种方法可以接受的情况,只是好奇,thanks@ultrajohn:如果你能绝对保证不会发生冲突,那么它至少是正确的——但我认为这仍然不是一个好主意。当然,你不能用HashSet来做这件事。不。集合存储对象,不允许通过键获取对象。这就是映射所做的。@Jon,java中所有基于哈希的映射,除了hashtable之外,都会对位进行加扰以“改进”哈希,所以独特的东西并不重要。floatToIntBits是可以的,这就是impl。不管怎样,都是java.lang.Float的,iirc。因为浮点数是32位的,所以不能更好地进行常规哈希运算,因为它们的可能值也小于2^32。HashMap的额外哈希看起来像h^=h>>20^h>>12;返回h^h>>>7^h>>4;由于pow2大小的bukets太多,需要额外的哈希,否则会与标准冲突太多hashes@Jon谢谢你的全面回答。在此,我要感谢所有回答我问题的其他人。我将使用HashMap。是否有这种方法可以接受的情况,只是好奇,thanks@ultrajohn:如果你能绝对保证不会发生冲突,那么它至少是正确的——但我认为这仍然不是一个好主意。当然,你不能用HashSet来做这件事。不。集合存储对象,不允许通过键获取对象。这就是映射所做的。@Jon,java中所有基于哈希的映射,除了hashtable之外,都会对位进行加扰以“改进”哈希,所以独特的东西并不重要。floatToIntBits是可以的,这就是impl。不管怎样,都是java.lang.Float的,iirc。因为浮点数是32位的,所以不能更好地进行常规哈希运算,因为它们的可能值也小于2^32。HashMap的额外哈希看起来像h^=h>>20^h>>12;返回h^h>>>7^h>>4;由于pow2大小的bukets太多,需要额外的哈希,否则会与标准冲突太多hashes@Jon谢谢你的全面回答。在此,我要感谢所有回答我问题的其他人。我将使用HashMap。有很多奇怪的东西:getClass!=但您仍然强制转换为SimpleEvent而不是Event。long上的Float.floatToIntBits也很奇怪。hashCode公式也没有多大意义,只是添加31?没有使用if Float.floatToIntBitsid!=浮球
oIntBitsother.id与if id相同!=托马斯·米勒说得对。这是由于类的前一个名称和其中变量的类型造成的。我在更改类名和变量类型时没有注意到它。有很多奇怪的事情:getClass!=但您仍然强制转换为SimpleEvent而不是Event。long上的Float.floatToIntBits也很奇怪。hashCode公式也没有多大意义,只是添加31?没有使用if Float.floatToIntBitsid!=Float.floatToIntBitsother.id与if id相同!=托马斯·米勒说得对。这是由于类的前一个名称和其中变量的类型造成的。我在更改类名和变量类型时没有注意到它。
events.get(3);
Map<Long, Event> id2event = new HashMap<Long, Event>();