【Java集合框架】3 - 10 HashMap 和 LinkedHashMap 集合
§3-10 HashMap
和 LinkedHashMap
集合
3-10.1 HashMap
集合
HashMap
位于 java.util
包下,是 Map
的一个实现类,其中没有独特的方法,一般直接使用 Map
中的方法即可。
HashMap
特点:
HashMap
与HashSet
的底层原理是一样的,后者在代码层面上实际上调用的就是HashMap
,在底层采用哈希表结构;- 同样地,在 JDK 8 前,采用数组 + 链表的方式存储;JDK 8 后,采用数组 + 链表 + 红黑树存储;
HashMap
的特点由键决定:无序、无重复、无索引;
HashMap
底层原理:
- 调用空参构造器,在内部会创建一个默认长度为 16,默认加载因子为 0.75 的数组;
- 调用
put
方法添加结点时,在底层会创建一个Entry
对象存储该结点,并仅计算键的哈希值,进一步得到结点的哈希地址; - 若该地址为空,则将该结点直接存入数组中;
- 若不为空,则会调用
equals
方法比较二者是否相等;若相等,则该结点直接覆盖此处的旧结点; - 若不相等,在 JDK 8 前,新结点存储到数组中,旧结点挂在新结点后形成链表;JDK 8 后,新结点直接挂在旧元素后形成链表;
- 自 JDK8 后,当数组长度大于等于 64 且链表长度大于 8 时,该链表自动转换为红黑树;
从底层原理看,HashMap
依赖 hashCode
和 equals
保证键的唯一性,自定义 Java Bean 类作为键时,必须重写这两个方法。
案例一:创建一个 HashMap
,键为学生对象(姓名、年龄),值为籍贯。在集合中添加三个学生对象并遍历;认为年龄与姓名相同则为同一个人。
HashMap<Student, String> hm = new HashMap<>();
Student s1 = new Student("Zhang San", 23);
Student s2 = new Student("Li Si", 24);
Student s3 = new Student("Wang Wu", 25);
Student s4 = new Student("Zhao Liu", 26);
Student s5 = new Student("Zhang San", 23);
System.out.println(hm.put(s1, "Guangdong"));
System.out.println(hm.put(s2, "Guangxi"));
System.out.println(hm.put(s3, "Fujian"));
System.out.println(hm.put(s4, "Beijing"));
System.out.println(hm.put(s5, "Beijing")); //键同则覆盖值
//遍历
hm.forEach((key, val) -> System.out.println(key + "=" + val));
案例二:某个班级里 80 个人,现有四个景点(A,B,C,D),每个人只能投一个景点,统计票数最多的景点。
HashMap<String, Integer> counter = new HashMap<>();
//选用更为通用的方法:若景点数目多,不可能提前添加在映射表
Random r = new Random();
//投票
for (int i = 0; i < 80; i++) {
String dest = String.valueOf(r.nextInt(4));
if (counter.containsKey(dest)) {
Integer val = counter.get(dest);
counter.put(dest, ++val); //自增后覆盖
} else
counter.put(dest, 1);
}
//遍历
counter.forEach((key, val) -> System.out.println((char) (Integer.parseInt(key) + 'A') + "=" + val));
//找最大值
int max = 0;
for (String key: counter.keySet()) {
if (max < counter.get(key))
max = counter.get(key);
}
String dest;
//找对应景点(可能有多个票数相同的)
for (String key: counter.keySet()) {
if (counter.get(key) == max) {
dest = key;
System.out.println("投票人数最多的景点为:" + (char)(Integer.parseInt(dest) + 'A') + "(" + max + ")");
}
}
3-10.2 LinkedHashMap
集合
LinkedHashMap
位于 java.util
包下,继承自 HashMap
,其中也没有独特的方法,一般直接使用 Map
中的方法即可。
LinkedHashMap
特点:
LinkedHashMap
的特点由键决定:有序、无重复、无索引;- 有序性指的是数据存取顺序一致;
LinkedHashMap
底层仍然使用哈希表,在此基础上额外引入了双向链表以记录存储顺序;