AbstractMap.SimpleEntry如何可变?

时间:2014-05-30 16:51:03

标签: java collections hashmap

如何同时AbstractMap.SimpleEntry

1)mutable(它的方法setValue()改变条目的值部分

2)定义了equals() / hashCode(),包括条目的值部分

3)成为Set<Map.Entry<T,K>> entrySet()结果

的一部分

在我看来,这三点是有争议的。例如,前两个违反Set<>接口的合同,该接口不建议使用该集合中的可变元素。

我可以肯定,Value的变异不会破坏地图吗?

为什么他们没有Entry只能按密钥进行比较和清除?这会在某些情况下提高速度吗?

4 个答案:

答案 0 :(得分:5)

  

我确定,Value的变异不会破坏地图吗?

是的,绝对的。 HashMap存储桶仅考虑条目的关键部分:

public V  [More ...] put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode()); // <<== HERE
    ...
}
  

为什么他们没有进入可比较且只能按键加密?这会在某些情况下提高速度吗?

hashCode的{​​{1}}和equals几乎没有相关性:只有当你想在 {{1}本身。提供给Map.Entry的呼叫者的HashMap的内部实现不使用条目的EntrySet / Map.entrySet - 而是使用仅密钥部分的哈希码。以下是在条目集中查找对象的相关源代码的一部分:

hashCode

答案 1 :(得分:0)

这可能是一个&#34;意见&#34;题。这是我最好的猜测。

我认为Set<Map.Entry<T,K>>可用,因此您可以迭代集合的元素以获取地图中的所有键/值对。但是,很少会使用此Set上的其他操作。特别是,似乎不太可能在这个集合上使用contains方法,这需要构建一个具有键的具体类的Map.Entry对象。价值,看看它是否在Set<Map.Entry<T,K>>中。由于我认为contains将是hashCode的主要用途,并且由于很少会使用contains,因此我不认为为hashCode()定义{ {1}}有很大用处,因此它不应引起关注。当然,Map.Entry存在,因为所有hashCode()都有它们;为什么他们觉得有必要正式定义其价值,我不知道。但我认为这是无害的。

答案 2 :(得分:0)

这里没有矛盾。您似乎错过的要点是entrySet() 不支持向其添加元素

因此,如果一个集合在地图返回时格式良好,那么

  1. 无法在集合中创建副本,因为您无法更改密钥或添加新条目,因此任何两个条目都将保持不同
  2. 可以更改Entry的哈希码,但不能影响密钥的哈希码,因此HashMaps不会中断 - 桶的条目仍然相同
  3. 无法更改已排序地图中Entry的位置。
  4. 实际上:setValue()不允许您更改关于地图如何处理条目的任何内容,因此将保留所有地图合约。

    我无法证明为什么equals()hashCode()以这种特定的方式实现,也许Java的作者有一个用例,我不知道。 (然后我再也没有考虑过这些方法的任何用例)

答案 3 :(得分:0)

AbstractMap.SimpleEntry的实现被认为是一个私有实现细节(它甚至不被所有Map实现使用,例如HashMap不使用它)。

请注意,没有API 直接公开此类型 - 可以说这个类可能已被保护或包私有而不是公共。

定义的公共API是Map.Entry(请注意,任何Map都返回一个Set)。 Entry的任何实现都需要符合此契约,并且在那里明确定义了hashCode实现。

使用SimpleEntry的类需要覆盖定义的一部分来处理其entrySet()实现所需的setValue() if (看看HashMap的一个例子如何处理)。注册的hashCode,虽然已经记录,但是通过entrySet()的实现并不是必然使用

至于&#34;为什么&#34;它是这样的:询问设计师。我猜想的是,没有更深层次的原因。