Java HashMap的三种遍历方法及优缺点含示例

发布时间:2024年01月24日

1. 前言

HashMap是一种基于哈希表的Map接口实现,主要用于存储键值对。它允许空值和空键。其主要特点是通过键的哈希值存储值,并提供了添加、获取和操作存储值的方法。

HashMap的底层数据结构是由数组和链表组成的。数组是HashMap的主体,而链表则是为了解决哈希冲突而存在的。当两个或更多的键的哈希值相同时,就会发生哈希冲突,此时,这些键值对就会存储在链表中。

在JDK1.8之前,当链表长度大于阈值(默认为8)时,链表会被转化为红黑树,以减少搜索时间。而在JDK1.8之后,这个阈值被改为64。这是因为红黑树在处理哈希冲突时,性能高于链表。当链表长度小于64时,会首先考虑数组扩容而不是转换为红黑树。

2. HashMap简介

HashMap 是 Java 中的一个重要数据结构,它实现了 Map 接口,提供了键值对(key-value pair)的存储和检索功能。HashMap 允许使用 null 作为键和值。

2.1 基本功能

  1. 存储键值对HashMap 存储了一系列的键值对,每个键唯一对应一个值。
  2. 快速检索HashMap 提供了基于键的快速检索功能,通常时间复杂度为 O(1)。

2.2 主要特性

  1. 无序HashMap 中的元素是无序的,即元素的插入顺序和遍历顺序可能不同。
  2. 允许 null 键和值HashMap 允许使用 null 作为键和值。
  3. 线程不安全HashMap 不是线程安全的,如果多个线程同时修改 HashMap,可能导致不可预期的结果。
  4. 可扩展HashMap 的大小可以根据需要动态调整。

2.3 实现细节

  1. 数组和链表HashMap 使用数组来存储键值对。每个数组元素是一个链表,用于存储具有相同哈希值的键值对。
  2. 哈希函数:每个键都有一个与之关联的哈希值,用于确定该键在数组中的位置。
  3. 扩容:当 HashMap 的负载因子超过某个阈值时,它会自动扩容以增加存储空间。
  4. 默认大小:默认情况下,HashMap 的初始大小为 16,并且每次扩容时大小翻倍。

2.4 使用场景

HashMap 在各种场景中都有广泛应用,例如:

  • 数据缓存:可以使用 HashMap 来缓存经常访问的数据,从而提高性能。
  • 数据统计:通过 HashMap 可以方便地统计各种数据元素的数量。
  • 查找表:可以用 HashMap 来实现查找表,快速查找某个键对应的值。
  • 数据库查询:在数据库查询中,可以使用 HashMap 来缓存查询结果,提高查询效率。

2.5 注意事项

  • 由于 HashMap 不是线程安全的,如果需要在多线程环境下使用,可以考虑使用 ConcurrentHashMap
  • 在使用 HashMap 时,需要考虑哈希函数的质量,以提高查找效率。

3. HashMap遍历

3.1 使用entrySet()方法

这是最常见的方法,它通过调用HashMap的entrySet()方法来获取一个包含所有键值对的Set集合,然后我们可以通过迭代这个集合来访问所有的键值对。示例代码如下:

Map<String, Integer> map = new HashMap<>();  
map.put("a", 1);  
map.put("b", 2);  
map.put("c", 3);  
  
for (Map.Entry<String, Integer> entry : map.entrySet()) {  
    String key = entry.getKey();  
    Integer value = entry.getValue();  
    System.out.println("Key: " + key + ", Value: " + value);  
}

3.2 使用keySet()方法

另一种遍历HashMap的方法是使用keySet()方法获取所有的键,然后使用get()方法获取对应的值。示例代码如下:

Map<String, Integer> map = new HashMap<>();  
map.put("a", 1);  
map.put("b", 2);  
map.put("c", 3);  
  
for (String key : map.keySet()) {  
    Integer value = map.get(key);  
    System.out.println("Key: " + key + ", Value: " + value);  
}

3.3 使用values()方法

最后一种方法是使用values()方法获取所有的值,然后使用getKey()方法获取对应的键。示例代码如下:

Map<String, Integer> map = new HashMap<>();  
map.put("a", 1);  
map.put("b", 2);  
map.put("c", 3);  
  
for (Integer value : map.values()) {  
    String key = map.getKey(value); // 需要先调用HashMap的getKey()方法获取键,该方法会遍历整个HashMap直到找到对应的键。因此,这种方法效率较低。  
    System.out.println("Key: " + key + ", Value: " + value);  
}

4. 总结

  1. 使用entrySet()方法:
    • 这是最常见的方法,通过调用HashMap的entrySet()方法来获取一个包含所有键值对的Set集合。
    • 返回的是一个Map.Entry对象的集合,每个Map.Entry对象包含了键和值。
    • 使用Iterator迭代Map.Entry对象,可以依次访问每个键值对。
    • 优点:直接获取键值对集合,便于遍历和操作。
    • 缺点:无。
  2. 使用keySet()方法:
    • 通过调用HashMap的keySet()方法来获取一个包含所有键的Set集合。
    • 返回的是一个Set集合,其中包含了所有的键。
    • 使用Iterator迭代Set集合,可以依次访问每个键。
    • 优点:获取键的集合比较方便。
    • 缺点:需要使用get()方法获取对应的值,可能存在性能开销。
  3. 使用values()方法:
    • 通过调用HashMap的values()方法来获取一个包含所有值的Collection集合。
    • 返回的是一个Collection集合,其中包含了所有的值。
    • 使用Iterator迭代Collection集合,可以依次访问每个值。
    • 优点:获取值的集合比较方便。
    • 缺点:需要使用getKey()方法获取对应的键,但该方法会遍历整个HashMap直到找到对应的键,效率较低。
文章来源:https://blog.csdn.net/a342874650/article/details/135820966
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。