为了只对地图进行一次查找并尽可能多地重用我的密钥实例,我想知道这样做是否合法:
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实现:
由于
答案 0 :(得分:3)
您应该避免在哈希映射中使用可变键。至少,您需要推迟已添加到哈希映射中的密钥的变异,直到将其从地图中删除为止。否则,变异的密钥将变为&#34;无法访问&#34;在地图内。
考虑这一系列事件(为简单起见,假设int
的哈希码是int
本身):
key
key
添加到哈希映射中;它将被散列到对应于代码为5
key
设置为6
。key
添加到地图中。此时,密钥将被散列到存储桶以获取6
的哈希码,并再次添加到地图中。queryKey
,一个值为5
的可变整数。尝试用它搜索哈希映射。此时,queryKey
的{{1}}将不再是&#34; connect&#34;到5
的旧密钥,即使它们具有相同的哈希码:位于5
的哈希桶中的key
实例也不会与5
相等},因为queryKey
的当前值为key
。实际上,旧密钥及其关联的映射条目变得无法访问。
答案 1 :(得分: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;