将java.util.Date存储为基于引用相等而不是“值”相等的Map中的键

时间:2014-12-31 10:38:55

标签: java date dictionary collections

我想构建一个Date对象的HashMap,所以每当我有两个不同的Date对象具有相同的Date值(day,month,year,..)时,Hashmap就不会用新的值替换过去的值。

示例:

    Date x = new Date();
    Date y = new Date();

    HashMap<Date,Integer> hm = new HashMap<Date,Integer>();
    hm.put(x,1);
    hm.put(y,3);

    System.out.println(hm.get(x));
    System.out.println(hm.get(y));

在这个例子中,他们都打印3.我想确保他们打印1然后3。

我已经考虑过将Hashmap中的键值作为每个日期的对象引用(因为它们会有所不同),那么如何强制执行该对象呢?

或者有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

您应该使用java.util.IdentityHashMap执行此任务。这样您就可以拥有equals,但Map中有不同的对象。

编辑: 你的例子:

Date x = new Date();
Date y = new Date();

Map<Date,Integer> hm = new IndentityHashMap<Date,Integer>();
hm.put(x,1);
hm.put(y,3);
assert hm.size() == 2: hm.size();

正如@BoristheSpider所指出的,当您丢失原始对象的引用时,这可能不是最好的数据结构。在这种情况下,MultiMap(例如guava)或ListEntry s / Pair s / Tuple可能是根据用例更好的选择。 (前者适用于您希望所有值都属于某些equals个键的情况,后者是访问所有键/值对,而不是按键搜索。)

如果您只想将Map作为“数组”使用随机访问某些或所有(存储的)密钥,IdentityHashMap是一个不错的选择。

答案 1 :(得分:0)

更好的解决方案是使用唯一的时间戳。这将确保您可以通过具有相同的时间戳来检索值。

private static final AtomicLong MILLIS = new AtomicLong();

public static Date newDate() {
    long now = System.currentTimeMillis();
    for(;;) {
        long prev = MILLIS.get();
        if (prev >= now)
            now = prev + 1;
        if (MILLIS.comapreAndSet(prev, now))
            return new Date(now);
    }
}

如果您使用此日期工厂,则每个数据都是唯一的,并且尽可能接近实际时间。

Date x = newDate();
Date y = newDate();

Map<Date,Integer> hm = new HashMap<>();
hm.put(x,1);
hm.put(y,3);

System.out.println(hm.get(x));
System.out.println(hm.get(y));