1

假设我希望检查HashMap条目然后替换它:

if( check( hashMap.get(key) ) ) {
    hashMap.put(key, newValue);
}

这将导致内部搜索过程HashMap运行两次:一次 whileget和另一次 while put。这看起来无效。是否可以修改已找到的 Map 条目的值?

更新

我知道我可以制作一个包装器,并且我知道我在改变条目时遇到了问题。但问题是为什么?可能是HashMap记得上次搜索改进重复一次?为什么没有方法来做这样的操作?

4

4 回答 4

3

编辑:我刚刚发现您可以Map.Entry.setValue通过(并且HashMap实现是可变的)修改条目。不过,获取特定键的条目是一件痛苦的事,而且我不记得曾经见过有人这样做。据我所知,您可以获得一条目,但无法获得单个键的条目。

有一种邪恶的做法 -HashMapjava.util包中声明您自己的子类,并创建一个仅委托给包私有现有方法的公共方法:

package java.util;

// Please don't actually do this...
public class BadMap<K, V> extends HashMap<K, V> {
    public Map.Entry<K, V> getEntryPublic(K key) {
        return getEntry(key);
    }
}

不过这很恶心。

您通常不会修改条目- 但当然您可以更改值中的数据,如果那是可变类型的话。

我非常怀疑这实际上是一个性能瓶颈,除非你经常这样做。在开始尝试微调可能不是问题的东西之前,您应该分析您的应用程序以向自己证明这是一个真正的问题。

如果它确实是一个问题,您可以将(比如说)a 更改Map<Integer, String>为 aMap<Integer, AtomicReference<String>>并将 theAtomicReference<T>用作简单的可变包装器类型。

于 2013-01-24T20:50:13.013 回答
2

对您的问题发表评论的信息太多。检查 Hashmap 的文档。

此实现为基本操作(get 和 put)提供恒定时间性能,假设哈希函数将元素正确地分散在桶中。集合视图的迭代需要的时间与 HashMap 实例的“容量”(桶的数量)加上它的大小(键值映射的数量)成正比。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低),这一点非常重要。

恒定时间意味着执行 get 和 put 操作总是需要相同的时间 [O(1)]。所需的时间量将是线性的,取决于您需要循环的次数 [O(n)]。

于 2013-01-24T21:10:10.147 回答
1

看看 trove ( http://trove4j.sourceforge.net/ ),他们的地图确实有几种你想要的方法:

  • 调整或放置
  • 放置如果不存在

我不知道这是如何在内部实现的,但我猜想由于 trove 是高性能的,所以只会有一个查找。

于 2013-01-24T21:00:56.583 回答
1

如果条目是可变的,您可以更改它。你可以这样做的一个例子是

private final Map<String, List<String>> map = new LinkedHashMap<>();

public void put(String key, String value) {
    List<String> list = map.get(key);
    if (list == null)
        map.put(key, list = new ArrayList<>());
    list.add(value);
}

这允许您更新一个值,但您无法在一次操作中查找和替换一个值。

于 2013-01-24T20:53:22.357 回答