【Java集合框架】3 - 10 HashMap 和 LinkedHashMap 集合

§3-10 HashMapLinkedHashMap 集合

3-10.1 HashMap 集合

HashMap 位于 java.util 包下,是 Map 的一个实现类,其中没有独特的方法,一般直接使用 Map 中的方法即可。

HashMap 特点

  • HashMapHashSet 的底层原理是一样的,后者在代码层面上实际上调用的就是 HashMap,在底层采用哈希表结构;
  • 同样地,在 JDK 8 前,采用数组 + 链表的方式存储;JDK 8 后,采用数组 + 链表 + 红黑树存储;
  • HashMap 的特点由键决定:无序、无重复、无索引;

HashMap 底层原理

  • 调用空参构造器,在内部会创建一个默认长度为 16,默认加载因子为 0.75 的数组;
  • 调用 put 方法添加结点时,在底层会创建一个 Entry 对象存储该结点,并仅计算键的哈希值,进一步得到结点的哈希地址;
  • 若该地址为空,则将该结点直接存入数组中;
  • 若不为空,则会调用 equals 方法比较二者是否相等;若相等,则该结点直接覆盖此处的旧结点;
  • 若不相等,在 JDK 8 前,新结点存储到数组中,旧结点挂在新结点后形成链表;JDK 8 后,新结点直接挂在旧元素后形成链表;
  • 自 JDK8 后,当数组长度大于等于 64 且链表长度大于 8 时,该链表自动转换为红黑树;

从底层原理看,HashMap 依赖 hashCodeequals 保证键的唯一性,自定义 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 底层仍然使用哈希表,在此基础上额外引入了双向链表以记录存储顺序;
posted @ 2023-08-11 18:41  Zebt  阅读(23)  评论(0)    收藏  举报