HashMap和Hashtable的遍历

本文介绍了两种遍历HashMap的方法:使用keySet()和entrySet()。同时对比了使用Hashtable进行遍历的过程。

 一.HashMap遍历,两种方法

    1.keySet()

       Person person1=new Person("zhangsan",20);
       Person person2=new Person("lisi",21);
       Person person3=new Person("wangwu",22);
       Map hm=new HashMap();
       hm.put("first", person1);
       hm.put("second", person2);
       hm.put("three", person3);
       Set keys=ht.keySet();
       Iterator it=keys.iterator();
  //遍历取出
  while(it.hasNext()){
   String key=(String)it.next();
   Person person=(Person)ht.get(key);
   System.out.println(person.getName()+"  "+person.getAge());
  }

    2.entrySet()

  Person person1=new Person("zhangsan",20);
  Person person2=new Person("lisi",21);
  Person person3=new Person("wangwu",22);
  Map hm=new HashMap();
  hm.put("first", person1);
  hm.put("second", person2);
  hm.put("three", person3);
  Set keys=hm.entrySet();
  Iterator it=keys.iterator();
  while(it.hasNext()){
   Map.Entry me=(Map.Entry)it.next();
   String key=(String)me.getKey();
   Person value=(Person)me.getValue();
   System.out.println("key : "+key);
   System.out.println("value : "+value.getName()+"  "+value.getAge());
  }

 

二.Hashtable遍历

     Hashtable ht = new Hashtable();//不能Map ht=new Hashtable();若加强制转换后,后面方法不能用
  ht.put("first", person1);
  ht.put("second", person2);
  ht.put("three", person3);
  Enumeration e=ht.elements();
  while(e.hasMoreElements()){
   Person person=(Person)e.nextElement();
   System.out.println(person.getName()+" "+person.getAge());
  }

 

### 底层结构差异 在底层结构上,HashMap Hashtable 存在一定的差异。从 JDK 1.8 开始,HashMap 的底层实现采用了数组 + 链表 + 红黑树的结构。这种结构优化了在哈希冲突较多时的性能,当链表长度超过一定阈值时,链表会转换为红黑树以提高查找效率[^2]。而 Hashtable 的底层实现则是传统的数组 + 链表结构,没有引入红黑树优化机制,因此在处理大量数据高冲突场景时性能相对较差[^2]。 ### 线程安全性 HashMap 是非线程安全的,这意味着在单线程环境下,它的性能更优由于没有同步开销。然而,在多线程环境下,如果多个线程同时修改 HashMap 的结构(例如添加或删除元素),可能会导致数据不一致或其他并发问题。因此,在多线程环境中使用 HashMap 需要额外的同步措施[^5]。相反,Hashtable 是线程安全的,它的所有公共方法都被 `synchronized` 关键字修饰,确保了多线程环境下的安全性,但这同时也带来了额外的性能开销[^5]。 ### 对 null 键 null 值的支持 HashMap 允许一个 null 键多个 null 值。这种灵活性使得 HashMap 在某些应用场景下更加方便。例如,可以轻松地将 null 作为特殊值进行处理[^3]。相比之下,Hashtable 不允许任何 null 键或 null 值。尝试插入 null 键或值会导致抛出 `NullPointerException` 异常[^3]。 ### 继承体系 HashMap 继承自 `AbstractMap` 类,并实现了 `Map` 接口。这样的设计使得 HashMap 能够更好地融入现代 Java 集合框架中,提供更简洁灵活的 API[^4]。而 Hashtable 继承自已废弃的 `Dictionary` 类,虽然它也实现了 `Map` 接口,但由于其继承体系的陈旧性,使得其 API 设计不如 HashMap 现代灵活[^4]。 ### 迭代器行为 HashMap 的迭代器是 fail-fast 的,这意味着在迭代过程中,如果检测到集合被修改(除了通过迭代器自身的 `remove` 方法),则会立即抛出 `ConcurrentModificationException` 异常。这种机制有助于快速发现并发修改问题[^4]。而 Hashtable 的迭代器不是 fail-fast 的,这可能导致在并发修改时出现不可预测的行为。 ### 扩容机制 当 HashMap 的容量不足以容纳更多元素时,它会按照当前容量的两倍进行扩容。这种策略有助于保持较低的负载因子,从而减少哈希冲突的概率。同样,Hashtable 也会在容量不足时进行扩容,但其扩容策略是当前容量的两倍加一。这种差异虽然看似微小,但在特定情况下可能会影响性能。 ### 推荐使用场景 由于 HashMap 在单线程环境下的高性能表现,它通常被推荐用于不需要线程安全的场景。此外,HashMap 的子类 `LinkedHashMap` 提供了可预测的迭代顺序(默认为插入顺序),这在某些需要有序遍历的应用中非常有用[^3]。而 Hashtable 由于其线程安全特性,更适合用于多线程环境或必须保证线程安全的场景。不过,对于需要高性能并发操作的场景,推荐使用 `ConcurrentHashMap`,因为它提供了更好的并发性能[^4]。 ### 示例代码 以下是一个简单的示例代码,展示了如何在 Java 中使用 HashMap Hashtable: ```java import java.util.HashMap; import java.util.Hashtable; import java.util.Map; public class Main { public static void main(String[] args) { // 使用 HashMap Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("one", 1); hashMap.put("two", 2); System.out.println("HashMap: " + hashMap); // 使用 Hashtable Map<String, Integer> hashTable = new Hashtable<>(); hashTable.put("one", 1); hashTable.put("two", 2); System.out.println("Hashtable: " + hashTable); } } ``` 这段代码演示了如何创建使用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值