Java hashMap中的自定义密钥生成和冲突
我有一个方法,可以将对象保存在hashmap(用作缓存)中,该hashmap的键是Java hashMap中的自定义密钥生成和冲突,java,hash,hashmap,collision-detection,hash-collision,Java,Hash,Hashmap,Collision Detection,Hash Collision,我有一个方法,可以将对象保存在hashmap(用作缓存)中,该hashmap的键是字符串 在方法中传递的对象具有“易失性”字段,即它们可以在数据存储的下一次刷新时更改,或者在除3个字段之外的所有对象中都相同。 这些字段是两个double类型的字段和一个String类型的字段 我现在做的是使用: Objects.hash(doubleField1, doubleField2, theString) 并将结果转换为字符串 基本上,我是基于不可变状态为该对象生成一个键 这似乎有效,但我有以下问
字符串
在方法中传递的对象具有“易失性”字段,即它们可以在数据存储的下一次刷新时更改,或者在除3个字段之外的所有对象中都相同。
这些字段是两个
double
类型的字段和一个String
类型的字段我现在做的是使用:
Objects.hash(doubleField1, doubleField2, theString)
并将结果转换为字符串
基本上,我是基于不可变状态为该对象生成一个键
这似乎有效,但我有以下问题:
如果我们排除两个对象具有完全相同的字段(这是不可能的)的情况,那么最终发生无法正确验证的冲突的可能性有多大?我的意思是,如果我有一个带有键的hashmap,例如字符串等,如果hashCode上有冲突,则会比较键的实际值,以验证它是否是同一个对象而不是冲突。
我所描述的使用密钥的方式会在这种验证中产生问题吗 更新:
例如,如果我有一个带有键a
Person
的hashmap,并且使用fullName
和ssn
或dateOfBirth
生成hashCode
,如果发生冲突,则hashmap实现使用equals
来验证它是否是正在搜索的实际对象。我想知道我所描述的方法在这一部分是否会有一些问题,因为我直接生成了实际的密钥。检索对象时,我逐段构造字段,以避免使用缓存的字符串或整数。这是一个更令人信服的演示
Map<MyKey, Long> map = new HashMap<>();
map.put(new MyKey(10,"abc"), 1234556L);
map.put(new MyKey(400,"aefbc"), 548282L);
int n = 380;
long v = map.get(new MyKey(n + 20, "ae" + "fbc")); // Should get 548282
System.out.println(v);
重点班
class MyKey {
privat eint v;
private String s;
private int hashcode;
public MyKey(int v, String s) {
Objects.requireNonNull(s, "String must be provided");
this.v = v;
this.s = s;
// this class is immutable so no need to keep
// computing hashCode
hashcode = Objects.hash(s,v);
}
@Override
public int hashCode() {
return hashcode;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null) {
return false;
}
if (o instanceof MyKey) {
MyKey mk = (MyKey)o;
return v == mk.v && s.equals(mk.s);
}
return false;
}
}
如果您谈论的是哈希代码发生变化的键,那么这是一个坏主意。键应该是不可变的。如果你说的是碰撞,那么我认为这不应该是个问题。hashCode实现可以返回一个类似42的常量。但是,您的地图将不会非常有效,因为它将退化为一个链接列表。但是我不完全确定你所说的验证是什么意思。
HashMap
(以及HashSet
)不仅通过hashcode()
识别对象,而且还通过equals()
识别对象。因此,重要的是要满足以下条件。@WJS:1)键不会改变。2) 例如,如果我有一个带有键aPerson
的hashmap,并且使用fullName
和ssn
或dateOfBirth
生成hashCode
,如果存在冲突,则hashmap实现使用equals
来验证它是否是正在搜索的实际对象。我想知道我所描述的方法在这方面是否会有问题如果您在HashMap
中使用散列作为键,并且发生冲突,则使用相同键存储在HashMap
中的第一个对象将丢失。是的。这是一种选择。
class MyKey {
privat eint v;
private String s;
private int hashcode;
public MyKey(int v, String s) {
Objects.requireNonNull(s, "String must be provided");
this.v = v;
this.s = s;
// this class is immutable so no need to keep
// computing hashCode
hashcode = Objects.hash(s,v);
}
@Override
public int hashCode() {
return hashcode;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null) {
return false;
}
if (o instanceof MyKey) {
MyKey mk = (MyKey)o;
return v == mk.v && s.equals(mk.s);
}
return false;
}
}