『卧槽』意外发现了 Hashtable 的 foreach 用法 BUG

这段时间,公司项目中 遇到一个问题,最后查出: 是 Hashtable 的用法导致的。

 

 1         private static void AutoCleanCache()
 2         {
 3             try
 4             {
 5                 lock (m_HashCache.SyncRoot)
 6                 {
 7                     List<object> listKey = new List<object>();
 8                     List<Tuple<string, DateTime, byte[]>> list = new List<Tuple<string, DateTime, byte[]>>();
 9                     if (m_HashCache.Count >= MAXCACHE)
10                     {
11                         //foreach (KeyValuePair<object, object> pair in m_HashCache)  //不能这样使用 Hashtable —— 可能会导致: 指定的转换无效 的异常
12                         foreach (object key in m_HashCache.Keys)
13                         {
14                             object value = m_HashCache[key];
15                             var svg = key as string;
16                             var bytes = value as Tuple<DateTime, byte[]>;
17                             if (string.IsNullOrWhiteSpace(svg) || (bytes == null || bytes.Item2 == null || bytes.Item2.Length <= 0)) listKey.Add(key);
18 
19                             list.Add(new Tuple<string, DateTime, byte[]>(svg, (bytes == null ? DateTime.MinValue : bytes.Item1), (bytes == null ? null : bytes.Item2)));
20                         }
21                     }
22 
23                     List<Tuple<string, DateTime, byte[]>> list2 = Enumerable.ToList(list.OrderBy(x => x.Item2).Take(list.Count / 2));
24                     foreach (var item in list2) listKey.Add(item.Item1);
25                     foreach (var key in listKey) m_HashCache.Remove(key);
26 
27                     listKey.Clear();
28                     list.Clear();
29                     list2.Clear();
30                 }
31             }
32             catch (Exception ex)
33             {
34                 logger.Warn(ex);
35             }
36         }

 

代码很丑 —— 各位不要介意。

我们只看重点代码:

1 //foreach (KeyValuePair<object, object> pair in m_HashCache) //不能这样使用 Hashtable —— 可能会导致: 指定的转换无效 的异常
2 foreach (object key in m_HashCache.Keys)

 

结论:

Hashtable 不要  foreach  KeyValuePair<object, object>

 

 

这下好了, 我这边 一堆底层代码 都遭殃了 ~ 

 

转载于:https://www.cnblogs.com/shuxiaolong/p/Hashtable_Foreach_BUG.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java中的Hashtable是一种基于哈希表的数据结构,用于存储键值对。它的使用方法如下: 1. 创建Hashtable对象: Hashtable<String, Integer> hashtable = new Hashtable<String, Integer>(); 2. 添加键值对: hashtable.put("key1", 1); hashtable.put("key2", 2); hashtable.put("key3", 3); 3. 获取值: int value = hashtable.get("key1"); 4. 判断是否包含某个键: boolean containsKey = hashtable.containsKey("key1"); 5. 判断是否包含某个值: boolean containsValue = hashtable.containsValue(1); 6. 删除键值对: hashtable.remove("key1"); 7. 获取所有键: Enumeration<String> keys = hashtable.keys(); 8. 获取所有值: Enumeration<Integer> values = hashtable.elements(); 注意:Hashtable是线程安全的,但是在多线程环境下,使用ConcurrentHashMap会更好。 ### 回答2: Java Hashtable是一个非常实用的数据结构,因为它可以将键和值的对映射起来,快速地在哈希表中查找和存储数据。要在Java中使用Hashtable,需要知道以下几个方面: 1. 创建Hashtable对象 要创建一个Hashtable对象,应该在Java中使用关键字“new”和Hashtable类名称,并将它们作为构造函数的参数。例如,要创建一个Hashtable对象,代码如下所示: Hashtable<String, String> hashtable = new Hashtable<String, String>(); 注意,这个语句通过使用“String”类型的键和值来创建了一个Hashtable对象。如果不指定键和值的类型,就会得到一个“Object”类型的Hashtable,这可能会导致类型转换问题。 2. 添加键和值 要在Hashtable中添加一个键和值,可以使用“put”方法。这个方法需要一个键和一个值作为参数,并将它们添加到Hashtable中。例如: hashtable.put("key1", "value1"); hashtable.put("key2", "value2"); hashtable.put("key3", "value3"); 3. 获取值 使用“get”方法可以获取Hashtable中的值。这个方法需要一个键作为参数,并返回与该键相关联的值。例如: String value1 = hashtable.get("key1"); String value2 = hashtable.get("key2"); String value3 = hashtable.get("key3"); 4. 删除键和值 要从Hashtable中删除一个键和值,可以使用“remove”方法。这个方法需要一个键作为参数,并删除与该键相关联的键和值。例如: hashtable.remove("key1"); 5. 遍历Hashtable 要遍历Hashtable中的键和值,可以使用“entrySet”和“for”循环。例如: Set<Entry<String, String>> set = hashtable.entrySet(); for (Entry<String, String> entry : set) { String key = entry.getKey(); String value = entry.getValue(); System.out.println("Key: " + key + ", Value: " + value); } 在上面的代码中,首先使用“entrySet”方法获取Hashtable中的所有键和值的集合。然后,循环遍历集合,并使用“getKey”和“getValue”方法获取每个键和值。 总之,Java Hashtable是一个非常实用的数据结构,可以快速地在哈希表中查找和存储数据。要使用Hashtable,需要创建Hashtable对象、添加键和值、获取值、删除键和值以及遍历Hashtable。 ### 回答3: Java Hashtable 是一个基于哈希表实现的 Map 接口,它可用于存储 key-value 键值对,其中每个键都是唯一的。与 HashMap 不同,Hashtable 是线程安全的,它的所有方法都是同步的,因此可以在多线程环境下使用,并且在性能方面与 HashMap 相近。 Java Hashtable 的基本用法如下: 1. 创建 Hashtable 对象: Hashtable<String, String> hashtable = new Hashtable<>(); 其中,"<String, String>" 表示键和值都是字符串类型,也可以使用其他数据类型,如 Integer、Double 等。 2. 添加元素: 添加元素可以使用 put() 方法: hashtable.put("key", "value"); 其中,"key" 表示键,"value" 表示值。 3. 获取元素: 获取元素可以使用 get() 方法: String value = hashtable.get("key"); 其中,"key" 表示键,"value" 表示值。 4. 删除元素: 删除元素可以使用 remove() 方法: hashtable.remove("key"); 其中,"key" 表示键。 5. 遍历元素: 遍历元素可以使用 Enumeration 或者 Iterator: (1)使用 Enumeration 遍历: Enumeration<String> keys = hashtable.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String value = hashtable.get(key); } 其中,keys() 方法返回了一个键的 Enumeration 对象,可以使用 hasMoreElements() 和 nextElement() 方法遍历所有键值对。 (2)使用 Iterator 遍历: Iterator<Map.Entry<String, String>> iterator = hashtable.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); String key = entry.getKey(); String value = entry.getValue(); } 其中,entrySet() 方法返回了一个包含所有键值对的 Set 对象,可以使用 iterator() 方法返回一个迭代器,然后使用 hasNext() 和 next() 方法遍历所有键值对。 以上就是 Java Hashtable 的基本用法,除了以上方法之外,Hashtable 还包含了其它一些重要的方法,如 contains、size() 等,可以根据实际需要使用。注意,在多线程环境下使用 Hashtable 时,需要使用 synchronized 或者 ConcurrentHashMap 等线程安全的集合类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值