2

为了只查找一次地图并尽可能多地重用我的关键实例,我想知道这样做是否合法:

    public static class GroupByOrdMap {
        private final Map<GroupByOrdKey, MutableInt> map = new HashMap<>();

        /**
         * Increment the value previously associated to key.
         * or add a new entry with value 1.
         * @param key the key
         * @return a reusale GroupByOrdKey or null if there is nothing to reuse
         */
        public GroupByOrdKey inc(GroupByOrdKey key) {
            MutableInt mu = new MutableInt(1);
            MutableInt prev = map.put(key, mu);
            if(prev != null) {
                mu.add(prev); // increment existing value
                // XXX : this key is mutable, but can I safely reuse this instance???
                return key;
            }
            return null;
        }
    }


// Key, as it can be heavy I would like to reuse it as much as possible 
public static class GroupByOrdKey {
    private long[] ords;

    public GroupByOrdKey(int size) {
        ords = new long[size];
    }

    private void setOrd(int idx, long ord) {
        ords[idx] = ord;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(ords);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        GroupByOrdKey other = (GroupByOrdKey) obj;
        if (!Arrays.equals(ords, other.ords))
            return false;
        return true;
    }
}

我只用 put 进行一次地图查找。但是我可以重用 GroupByOrdKey 实例吗?Javadoc 没有说清楚,值被替换了,但是键实例呢?

是否有任何其他允许此类用例的 Map 实现:

  • 只有一个地图查找
  • 重用现有的密钥实例

谢谢

4

2 回答 2

3

您应该避免在哈希映射中使用可变键。至少,您需要将已添加到哈希映射中的键的突变推迟到从映射中删除之后。否则,变异的键将在地图内变得“无法访问”。

考虑这个事件序列(为简单起见,假设 an 的哈希码int是它int本身):

  • 创建一个key值为 5的可变整数
  • 添加key到哈希映射;它将被散列到对应于具有代码的桶中5
  • 设置key6
  • 再次尝试添加key到地图。此时,密钥将被哈希到哈希码的桶中6,并再次添加到映射中。
  • 创建一个查询键queryKey,一个值为 的可变整数5。尝试用它搜索哈希图。

此时,queryKeyof5将不再“连接”到 的旧键5,即使它们具有相同的哈希码:key坐在哈希桶中的实例5不会与 相等queryKey,因为key的当前值为6. 本质上,旧密钥及其关联的映射条目变得无法访问。

于 2013-05-30T13:26:47.020 回答
0

它可能会起作用,但几乎可以肯定它是不可移植的。原因 - 很可能在HashMap代码中的某个地方会有:

...
if ( thisKey == thatKey ) {
  // They are the same object - they MUST be equal.
  ...
  code that will not be executed for you but you probably wish it was
}

如果你没有,那么其他人可能也会有。

实际上,看起来您在自己的equals方法中执行此操作:

    ...
    if (this == obj)
        return true;
于 2013-05-30T13:32:32.330 回答