重置hashmap中的所有值而不进行迭代?

时间:2014-03-31 14:53:51

标签: java hashmap

如果条件失败,我正尝试将HashMap中的所有值重置为某个默认值。

目前我通过迭代所有键并单独重置值来实现这一点。
有没有可能的方法为所有键设置相同的值而不进行迭代?

类似的东西:

hm.putAll("some val")  //hm is hashmap object

6 个答案:

答案 0 :(得分:6)

您无法避免迭代,但如果您使用,则可以使用replaceAll方法为您执行此操作。

  

将指定的函数应用于此映射中的每个条目,替换每个条目   条目的值与调用函数的函数#map的结果   使用当前条目的键和值的方法。

m.replaceAll((k,v) -> yourDefaultValue);

基本上它迭代遍历映射表的每个节点,并影响每个值的函数返回值。

@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
    Node<K,V>[] tab;
    if (function == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node<K,V> e = tab[i]; e != null; e = e.next) {
                e.value = function.apply(e.key, e.value); //<-- here
            }
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

示例:

public static void main (String[] args){ 
    Map<String, Integer> m = new HashMap<>();
    m.put("1",1);
    m.put("2",2);

    System.out.println(m);
    m.replaceAll((k,v) -> null);
    System.out.println(m);
}

输出:

{1=1, 2=2}
{1=null, 2=null}

答案 1 :(得分:5)

你不能以某种方式避免迭代。

您可以通过Map.values()获取值并迭代这些值。您可以绕过按键查找,它可能是最有效的解决方案(尽管我怀疑通常会为您节省相对较少,也许对于您的代码的随意读者来说,这不是最明显的)

答案 2 :(得分:1)

恕我直言你必须创建自己的数据结构,从谷歌扩展。然后你可以编写你的方法resetAll()并给出默认值。 Map是一个快速平衡的树,允许您快速地在结构中行走并设置值。不用担心速度,因为树在重置之前和之后将具有相同的结构。 只是,小心并发线程。也许你应该使用ConcurrentHashMap。

public class MyMap<K,V> extends ConcurrentHashMap<K, V>{

  public void resetAll(V value){
    Iterator<Entry<K, V>> it = this.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pairs = (Map.Entry)it.next();
        pairs.setValue( value );
    }
  }

}

此致

答案 3 :(得分:0)

如果你愿意复制它(带有默认值的hashmap) 您可以先清除哈希值,然后移动默认值

hm.keySet().removeAll();
hm.putAll(defaultMap);

答案 4 :(得分:0)

不可能在小于O(n)时间内对集合中的所有值应用操作,但是如果您的异议本身就是迭代本身,则有一些可能的替代方案,特别是函数式编程。

Guava库(或原生于Java 8)和functional programming utilities使这变得最容易。他们的Maps.transformValues()提供了地图的视图,并应用了提供的功能。这意味着函数在O(1)时间内返回,与迭代不同,但只要从返回的映射中.get(),计算就会立即完成。这显然是一种权衡 - 如果您只需要.get()转换后的地图中的某些元素,您可以通过避免计算不必要的值来节省时间。另一方面,如果你知道你以后会至少击中每个元素一次,使用这种行为意味着你实际上会浪费时间。实质上,这种方法是O(k),其中k是您计划执行的查找次数。如果k始终小于n,则使用转换方法是最佳的。

仔细阅读页面顶部的警告;迭代是一种简单,易用且通常理想有效的方式来处理地图成员。你应该只在绝对必要时尝试优化过去。

答案 5 :(得分:0)

假设你的问题不在于自己进行迭代,而是因为O(n)在某个时刻正在进行,我建议采用几种替代方法。请记住,我不知道你使用的是什么,所以它对你没有任何意义。

案例A :如果您的密钥组已知且已预先修复,请在某处复制(不是参考,实际克隆),并将值重置为您想要的值。然后在你提到的那个条件下,只需切换引用即可使用默认值。

案例B :如果密钥随时间变化,请使用案例A中的提示,但为添加的每个新密钥添加新条目(或相应删除)。您的更新几乎不会被注意到,但您仍然可以切换回O(1)中的默认值。