Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java hashMap中的自定义密钥生成和冲突_Java_Hash_Hashmap_Collision Detection_Hash Collision - Fatal编程技术网

Java 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) 并将结果转换为字符串 基本上,我是基于不可变状态为该对象生成一个键 这似乎有效,但我有以下问

我有一个方法,可以将对象保存在hashmap(用作缓存)中,该hashmap的键是
字符串

在方法中传递的对象具有“易失性”字段,即它们可以在数据存储的下一次刷新时更改,或者在除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) 例如,如果我有一个带有键a
Person
的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;
    }
}