在本文中,我们将通过示例讨论在 Java 上遍历 HashMap 的五种最佳方法。
- 使用Iterator迭代
- 使用 For-each + entrySet 循环遍历 HashMap
- 使用 For-each + keySet 循环遍历 HashMap
- 使用 Lambda 表达式遍历 HashMap
- 使用 Stream API 遍历 HashMap
首先我们先了解一下HashMap的基础知识和常用方法
一、对于Map集合存储结构的理解
首先介绍以HashMap为典型代表的Map集合的存储结构
① Map中的key:无序的、不可重复的,底层使用Set集合存储key;key所在的类要重写equals()和hashCode() 。
② Map中的value:无序的、可重复的,底层使用Collection集合存储value;value所在的类要重写equals() 。
③ Map中的entry:无序的、不可重复的,底层使用Set集合存储entry,每个entry都相当于一组
key-value 。
二、HashMap的常用方法
如果想要使用HashMap,我们需要对HashMap的常用方法有一个基本的了解:
* 添加:put(Object key,Object value)
* 删除:remove(Object key)
* 修改:put(Object key,Object value)
* 查询:get(Object key)
* 长度:size()
* 遍历:keySet() / values() / entrySet()
三、五种循环方式的代码展示
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
*/
public class App {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "C");
map.put(2, "C++");
map.put(3, "Java");
map.put(4, "Spring Framework");
map.put(5, "Hibernate ORM framework");
/**
* 1.使用Iterator迭代
* 首先,它是遍历老java版本map的唯一方法。
* 另外一个重要的特性是可以让你在迭代的时候从map中删除entries的(通过调用iterator.remover())唯一方法。
* 如果你试图在For-Each迭代的时候删除entries,你将会得到unpredictable resultes 异常。
* 从性能方法看,这个方法等价于使用For-Each迭代
*/
System.out.println("1.使用Iterator迭代");
// 使用 EntrySet
Iterator<Entry<Integer, String>> iterator1 = map.entrySet().iterator();
while (iterator1.hasNext()) {
Entry<Integer, String> entry = iterator1.next();
System.out.print("key:" + entry.getKey() + ",");
System.out.println("value:" + entry.getValue());
}
// 使用 KeySet
Iterator<Integer> iterator2 = map.keySet().iterator();
while (iterator2.hasNext()) {
Integer key = iterator2.next();
System.out.print("key:" + key + ",");
System.out.println("value:" + map.get(key));
}
System.out.println("-------------------------------------");
/**
* 2.使用 For-each + entrySet 循环遍历 HashMap
* 这是最常见的方法,并在大多数情况下更可取的。当你在循环中需要使用Map的键和值时,就可以使用这个方法
*
* 注意:For-Each循环是Java5新引入的,所以只能在Java5以上的版本中使用。
* 如果你遍历的map是null的话,For-Each循环会抛出NullPointerException异常,所以在遍历之前你应该判断是否为空引用。
*/
System.out.println("2.使用 For-each + entrySet 循环遍历 HashMap");
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.print("key:" + entry.getKey() + ",");
System.out.println("value:" + entry.getValue());
}
System.out.println("-------------------------------------");
/**
* 3.使用 For-each + keySet 循环遍历 HashMap
* 如果你只需要用到map的keys 或 values时,你可以遍历KeySet或者values代替entrySet
* 这个方法比entrySet迭代具有轻微的性能优势(大约快10%)并且代码更简洁
*
* 注意:如果使用迭代keys并搜索values是低效的
* 通过key得到value值更耗时(这个方法在所有实现map接口的map中比方法#2慢20%-200%)。
* 如果你安装了FindBugs,它将检测并警告你这是一个低效的迭代。这个方法应该避免
*/
System.out.println("3.使用 For-each + keySet 循环遍历 HashMap");
for (Integer key : map.keySet()) {
System.out.println("key:" + key + ",");
// key得到value 低效的
// System.out.println("value:" + map.get(key));
}
for (String value : map.values()) {
System.out.println("value:" + value);
}
System.out.println("-------------------------------------");
/**
* 4.使用Lambda表达式遍历HashMap
* 底层实际就是方法#2 但是写法较为简洁
*/
System.out.println("4.使用Lambda表达式遍历HashMap");
map.forEach((key, value) -> {
System.out.print("key:" + key + ",");
System.out.println("value:" + value);
});
System.out.println("-------------------------------------");
/**
* 5.使用Stream API遍历HashMap
*/
System.out.println("5.使用Stream API遍历HashMap");
map.entrySet().stream().forEach((entry) -> {
System.out.print("key:" + entry.getKey() + ",");
System.out.println("value:" + entry.getValue());
});
}
}