在前几篇文章中,我们主要分析了集合框架中的 ArrayList,在实际开发中,另一种很常用的集合框架就是 Map,它作为Java中典型的键值对结构的数据结构,相信大家对它也不陌生。本文我们来分析一下 Map 中的 HashMap。
HashMap 介绍
HashMap 是一种常用的数据结构,是一个非线程安全的集合,主要用来存放键值对。在 JDK1.8 之前 HashMap 由数组+链表 实现,链表主要用于解决哈希冲突;在 JDK1.8 之后,JDK 选择了新的哈希冲突解决方式,当链表长度大于一定阈值,HashMap 会将链表转化为红黑树,以此提高 HashMap 的效率。
常用方法
创建 HashMap
HashMap<K,V> 和其他的集合框架一样都是泛型类,并且它有两个泛型,分别代表键(K)和值(V)。最简单的创建方法就是调用 HashMap 的无参构造方法。
HashMap<String, Integer> map = new HashMap<>();
添加元素
集合框架中最常用的方法就是添加元素,通过 put()
在 map 中添加键值对,入参需要和创建实例时的泛型类型一致。
map.put("苹果", 15);
map.put("香蕉", 20);
map.put("梨", 18);
// {苹果=15, 香蕉=20, 梨=18}
如果用put()
方法添加了一个已经存在的键,那么map会更新键的值,保存最新的键值对。
map.put("苹果", 15);
map.put("香蕉", 20);
map.put("梨", 18);
map.put("香蕉", 60);
// {苹果=15, 香蕉=60, 梨=18}
删除元素
和添加元素对于的方法就是删除元素,传入要删除的 key
进行删除
map.remove("苹果");
当然如果需要删除map内全部的键值对,也可以使用 clear()
方法,表示情况全部元素
map.clear();
获取值
如果知道键的话,可以通过 get()
方法获取相对应的值。
map.get("香蕉");
// 60
判断键是否存在
通过 containsKey()
方法,入参为键,返回是否存在这个键(true/false)
map.containsKey("苹果");
// false
map.containsKey("梨");
// true
获取键的集合
使用 keySet()
方法获取键的集合,我们也可以使用这个方法进行 map 的遍历
map.keySet();
// [香蕉, 梨]
获取键值对集合
entrySet()
方法可以获取到 map 的键值对集合,返回一个 Set<Map.Entry<K,V>>
类型的集合。同样的,这个方法也可以用作遍历。
map.entrySet();
// [香蕉=60, 梨=18]
遍历 Map
遍历是开发中常常用到的,我们介绍一下 map 的常用遍历方式,更详细的介绍以及各种方法的效率,可以参考HashMap 的 7 种遍历方式与性能分析!
// 1. 通过Map的KeySet,遍历key和value
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + ": " + value);
}
// 2. 迭代器遍历
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
// 3. 通过遍历Map的values,只能遍历value,获取不到key --- 只需要value值时效率最高
for (Integer value : map.values()) {
System.out.println(value);
}
// 4. 通过entrySet,遍历key value。 --- 效率最高!
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
// 5. lambda表达式遍历
map.forEach((key, value) -> System.out.println("key: " + key + ", value: " + value));