0

我想要一个 DateWrapper - 代表一个日期(为 Hibernate 持久性而构建,但这是另一个故事) - 最多在同一日期同时存在。

我对冲突和散列的好键有点困惑。我正在为一个DateWrapper对象编写一个工厂,并且我想使用解析日期的毫秒数作为键,就像我看到其他人所做的那样。但是,如果发生碰撞会发生什么?. 毫秒总是彼此不同,但内部表可能小于可能存在的 Long。并且一旦哈希映射发生冲突,它就会使用等号,但是它如何区分两个不同的对象和我的 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;
    }

}
4

4 回答 4

0

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

附带说明一下,如果有任何并发​​的机会,您可能希望使用 ConcurrentHashMap 和putIfAbsent()而不是非原子的 get/if/put 调用。

于 2010-11-15T19:27:42.150 回答
0

equals()在长键上调用,而不是值。你很好。

于 2010-11-15T19:32:25.733 回答
0

如果您使用您想要的实际对象作为映射键,并让HashMap处理这些对象的哈希码(以及键实现equalshashCode根据他们的合同)的详细信息,那么如果有哈希码就没有问题除了由于需要线性搜索散列到同一个桶的每个条目而导致的一些可能的性能降低之外的冲突。

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

这个故事的寓意是:使用实际的密钥或绝对等价的东西(如DateTime本例中的毫秒)作为密钥,而不是密钥的哈希码。使用HashMap哈希码为您完成所需的工作。

于 2010-11-15T20:35:01.957 回答
0

考虑到您最终要通过此实现的目标,这似乎并没有太大的成效。您有一个高度优化的数据结构,专为快速搜索和强制唯一性而设计,称为数据库索引。Hibernate 已经为您提供了极其强大的内存和 L2 缓存。顺便说一下,没有将 HashMap 放在静态字段上的线程安全问题。

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

于 2010-11-15T20:57:44.443 回答