【问题标题】:remove element of an hashtable in the iteration在迭代中删除哈希表的元素
【发布时间】:2011-03-04 06:11:23
【问题描述】:

下面的代码是删除哈希表中元素的安全方法吗?

   Enumeration keys = siCache.keys();  //siCache is Hashtable

    while(keys.hasMoreElements())
    {
        String k = (String) keys.nextElement();
        Object v = siCache.get(k);

       if(condition) siCache.remove(k);

    }

【问题讨论】:

  • 我不明白为什么这些元素会被转换为StringHashTable.remove 需要密钥本身,而不是它的 toString。如果您的情况出于某种原因需要String,那很好,但不要使用 ity 作为HashTable.remove 的参数
  • 好像。您认为这不安全有什么特别的原因吗?
  • @Jon_darkstar 问:toString() 与强制转换为 String 有什么关系?答:没什么。
  • 对,好点。我最近不怎么用java。尽管如此,我关于选角目的的问题仍然存在,即使该细节已关闭

标签: java hashtable


【解决方案1】:

使用入口集、键集或值集的Iterator,调用Iterator.remove()

【讨论】:

  • 不,还有另一种安全的技术:使用密钥集的迭代器及其remove() 方法。 :)
  • 想提供一个完整的例子吗?我是java新手。谢谢
  • 另一种安全技术:使用 VALUE 的迭代器及其 remove() 方法。 :)
【解决方案2】:

在枚举键的同时从Hashtable 中删除元素存在潜在风险。这是 javadoc 所说的:

“因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。Hashtable 的键和元素方法返回的枚举是不能快速失败。”

含义很明确:如果你这样做,任意的、非确定性的行为是可能的。

解决方案:

  • 如果您使用的是 J2SE,请使用 keySet()。或者更好的是,不要使用Hashtable
  • 如果您使用的是 J2ME,请构建要删除的密钥列表,并在以后删除它们......或者努力祈祷:-)。

【讨论】:

    【解决方案3】:

    使用...之间有明显的区别

    Enumeration keys = siCache.keys();
    

    并使用...

    Iterator iterator = siCache.entrySet().iterator()
    

    当您在迭代时删除集合中的元素时,选项 1 不会引发 ConcurrentModificationException,而选项 2 会。

    至于为什么...我相信当您在示例中创建键 Enumeration 时,它是表键集的文字副本,与表本身的修改不同步。

    这对您来说可能是也可能不是问题。如果表同时使用,但您可能希望切换到使用集合迭代器。

    【讨论】:

      【解决方案4】:

      这是安全的。但是是什么让你认为它可能不是?

      使用以下代码进行测试。

      public static void main(String[] args) {
              // TODO Auto-generated method stub
      
              Hashtable siCache = new Hashtable();
              siCache.put("key", "value");
              siCache.put("key1", "value1");
              Enumeration keys = siCache.keys();  //siCache is Hashtable
      
              while(keys.hasMoreElements())
              {
                  String k = (String) keys.nextElement();
                  Object v = siCache.get(k);
      
                 if(true) siCache.remove(k);
      
              }
              System.out.println(siCache.size());
          }
      

      输出:0

      【讨论】:

      • 而且这个例子也不能证明什么。
      猜你喜欢
      • 2011-04-28
      • 2013-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 2011-11-17
      相关资源
      最近更新 更多