Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.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_Hashmap_Key_Hash Collision - Fatal编程技术网

Java HashMap冲突:我的代码正确吗?

Java HashMap冲突:我的代码正确吗?,java,hashmap,key,hash-collision,Java,Hashmap,Key,Hash Collision,我希望有一个DateWrapper—表示一个日期(为Hibernate持久性而构建,但这是另一个故事)—最多在同一时间存在于同一日期 我对冲突和哈希的好键有点困惑。我正在为一个DateWrapper对象编写一个工厂,我想使用解析日期的毫秒数作为键,就像我看到其他人所做的那样但是,如果发生碰撞会发生什么?。毫秒之间总是不同的,但是内部表可能小于可能存在的长度。一旦散列映射发生冲突,它就使用equals,但是它如何区分两个不同的对象和我的Long?也许,这是put方法来删除(覆盖)一些我想插入的值。

我希望有一个DateWrapper—表示一个日期(为Hibernate持久性而构建,但这是另一个故事)—最多在同一时间存在于同一日期

我对冲突和哈希的好键有点困惑。我正在为一个
DateWrapper
对象编写一个工厂,我想使用解析日期的毫秒数作为键,就像我看到其他人所做的那样但是,如果发生碰撞会发生什么?。毫秒之间总是不同的,但是内部表可能小于可能存在的长度。一旦散列映射发生冲突,它就使用equals,但是它如何区分两个不同的对象和我的Long?也许,这是put方法来删除(覆盖)一些我想插入的值。。。 那么,这段代码是安全的,还是被窃听了

package myproject.test;

import java.util.HashMap;
import java.util.Map;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import myproject.utilities.DateWrapper;

public class DateWrapperFactory {

    static Map <Long, DateWrapper> cache = new HashMap<Long, DateWrapper>();
    static DateTimeFormatter parser =
        DateTimeFormat.forPattern("yyyy-MM-dd");

    static DateWrapperFactory instance = new DateWrapperFactory();

    private DateWrapperFactory() {
    }

    public static DateWrapperFactory getInstance() {
        return instance;
    }


    public static DateWrapper get(String source) {
        DateTime d = parser.parseDateTime(source);
        DateWrapper dw = cache.get(d.getMillis());
        if (dw != null) {
            return dw;
        } else {
            dw = new DateWrapper(d);
            cache.put(d.getMillis(), dw);
            return dw;
        }
    }

}

package myproject.test;

import org.joda.time.DateTime;

public class DateWrapper {

    private DateTime date;

    public DateWrapper(DateTime dt) {
        this.date = dt;
    }

}
包myproject.test;
导入java.util.HashMap;
导入java.util.Map;
导入org.joda.time.DateTime;
导入org.joda.time.format.DateTimeFormat;
导入org.joda.time.format.DateTimeFormatter;
导入myproject.utilities.DateWrapper;
公共类DateWrapperFactory{
静态映射缓存=新的HashMap();
静态日期时间格式分析器=
模式的日期时间格式(“yyyy-MM-dd”);
静态DateWrapperFactory实例=新建DateWrapperFactory();
私有DateWrapperFactory(){
}
公共静态DateWrapperFactory getInstance(){
返回实例;
}
公共静态日期包装器获取(字符串源){
DateTime d=parser.parseDateTime(源);
DateWrapper dw=cache.get(d.getMillis());
如果(dw!=null){
返回数据仓库;
}否则{
dw=新的日期包装器(d);
cache.put(d.getMillis(),dw);
返回数据仓库;
}
}
}
包myproject.test;
导入org.joda.time.DateTime;
公共类日期包装器{
私人日期时间日期;
公共日期包装器(DateTime dt){
这个日期=dt;
}
}

使用HashMap,您只能在任何给定键值下存储一个条目(例如,在您的情况下为Long)


另一方面,如果有并发的可能,您可能希望使用ConcurrentHashMap,而不是非原子的get/if/put调用。

将在长键上调用
equals()
。您很好。

如果您使用您想要的实际对象作为映射键,并让
HashMap
处理这些对象的hashcode的细节(并且这些键根据它们的约定实现
等于
hashcode
)如果存在哈希代码冲突,除了由于需要线性搜索散列到同一个bucket的每个条目而导致性能降低之外,不会有任何问题

在你的另一个问题中,碰撞的主题出现了一个问题,那就是你没有使用应该是键的实际对象,而是使用该对象的哈希代码作为键本身。这是不正确的,会导致不正确的行为。。。。当您在映射中查找给定键的值时,结果可能是实际映射到一个完全不同的键的值,该键恰好具有相同的哈希代码


这个故事的寓意是:使用实际的键或绝对等效的东西(如本例中的
DateTime
的毫秒)作为键,而不是键的哈希码。
HashMap
可以满足您对hashcode的需求。

考虑到您最终要用它来完成的任务,这似乎不是非常有效。您有一个高度优化的数据结构,专门为快速搜索和强制唯一性而设计,称为数据库索引。从Hibernate开始,内存和二级缓存已经非常健壮。顺便说一句,它没有在静态字段上放置HashMap的线程安全问题


为什么不让这个数字成为数据库中ID列的值,让健壮的平台技术快速查找并缓存它呢?内存中二级缓存命中的速度实际上并不比总体方案中的HashMap慢多少。这将是一个非常罕见的应用程序,其中差异是您有意义的热点之一。

抱歉,但地图使用的相等值是关键之一,不是吗?所以,我认为使用的不是DateWrapper的等价物,而是Long的等价物。事实上,这取决于你想要完成什么。听起来您选择的数据结构并不能满足您的需要。请更新您的问题,以表明您正在尝试做什么。完成(添加第一句)。我希望在同一时间内最多有一个DateWrappervalue@cdarwin:您也可以将
DateTime
本身作为映射键,尽管我认为您所拥有的将起作用(当然,除非在多个线程上调用
get
),你打算用它们做什么?为什么它们一开始就在一个散列中?@ColinD:那么他就必须自己实现equals()。现在还不清楚他到底想做什么,甚至HashMap是否是正确的数据结构。这是否相当于一个集合,通过getMillis()实现DateTime.equals?@extraneon:这不是等价的。这里的想法(我认为)是为每个使用的
DateTime
实现一个规范/内部实例,这需要能够在不迭代的情况下获取该实例。。。这需要一张地图。好的,谢谢你,科林。我知道这一点,但混淆源于使用了一个键,该键对于您所引用的代码中的对象来说不是唯一的(对于其他读者,请参阅)。因此,它相当简单:hashmap中使用的键必须与一个且仅与一个对象对应,就像RDBMS中的主键一样