Java:集合Map:HashMap,LinkedHashMap,TreeMap

发布于:2025-07-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

HashMap

  1. 键无序、不重复、无索引

Set底层就是HashMap,Map的集合的值忽略不看就是Set集合

  1. HashMap底层数据结构: 哈希表结构
    JDK8之前的哈希表 = 数组+链表
    JDK8之后的哈希表 = 数组+链表+红黑树
  2. 哈希表是一种增删改查数据,性能相对都较好的数据结构

(了解)往HashMap集合中键值对数据时,底层步骤如下

第1步:当你第一次往HashMap集合中存储键值对时,底层会创建一个长度为16的数组
第2步:把键然后将键和值封装成一个对象,叫做Entry对象
第3步:再根据Entry对象的键计算hashCode值(和值无关)
第4步:利用hashCode值和数组的长度做一个类似求余数的算法,会得到一个索引位置
第5步:判断这个索引的位置是否为null,如果为null,就直接将这个Entry对象存储到这个索引位置
如果不为null,则还需要进行第6步的判断
第6步:继续调用equals方法判断两个对象键是否相同
如果equals返回false,则以链表的形式往下挂
如果equals方法true,则认为键重复,此时新的键值对会替换就的键值对。

(了解)HashMap底层需要注意这几点

  1. 底层数组默认长度为16,如果数组中有超过12个位置已经存储了元素,则会对数组进行扩容2倍
    数组扩容的加载因子是0.75,意思是:16*0.75=12
  2. 数组的同一个索引位置有多个元素、并且在8个元素以内(包括8),则以链表的形式存储
    JDK7版本:链表采用头插法(新元素往链表的头部添加)
    JDK8版本:链表采用尾插法(新元素我那个链表的尾部添加)
  3. 数组的同一个索引位置有多个元素、并且超过了8个,则以红黑树形式存储

(重要)为什么要重写hashCode() 和 equals()方法

从HashMap底层存储键值对的过程中我们发现:决定键是否重复依赖与两个方法,一个是hashCode方法、一个是equals方法。有两个键计算得到的hashCode值相同,并且两个键使用equals比较为true,就认为键重复。

所以,往Map集合中存储自定义对象作为键,为了保证键的唯一性,我们应该重写hashCode方法和equals方法。

LinkedHashMap

有序的、不重复、无索引

  • 有序指的是存取数据顺序一致

  • 注意:只有TreeMap的键才能排序,HashMap键不能排序。

TreeMap

  • 默认按照键的升序排列,键不重复,无索引
  • TreeMap集合的底层原理和TreeSet也是一样的,底层都是红黑树实现的。所以可以对键进行排序。

两种方法指定排序规则

字符串,基本类型等可以排序,但是自定义类型不知道以什么规则进行排序,输出的时候就会报错(输出的时候先排序再输出)

  1. 写一个Student类,让Student类实现Comparable接口
    重写CompareTo()方法
//第一步:先让Student类,实现Comparable接口
public class Student implements Comparable<Student>{
    private String name;
    private int age;
    private double height;
	//无参数构造方法
    public Student(){}
    //全参数构造方法
    public Student(String name, int age, double height){
        this.name=name;
        this.age=age;
        this.height=height;
    }
    //...get、set、toString()方法自己补上..
    
    //按照年龄进行比较,只需要在方法中让this.age和o.age相减就可以。
    /*
    原理:
    在往TreeSet集合中添加元素时,add方法底层会调用compareTo方法,根据该方法的
    结果是正数、负数、还是零,决定元素放在后面、前面还是不存。
    */
    @Override
    public int compareTo(Student o) {
        //this:表示将要添加进去的Student对象
        //o: 表示集合中已有的Student对象
        return this.age-o.age;
    }
}
  1. 在创建TreeMap集合时,直接传递Comparator比较器对象。(匿名内部类)
/**
 * 目标:掌握TreeMap集合的使用。
 */
public class Test3TreeMap {
    public static void main(String[] args) {
        Map<Student, String> map = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Double.compare(o1.getHeight(), o2.getHeight());
            }
        });
//        Map<Student, String> map = new TreeMap<>(( o1,  o2) ->   Double.compare(o2.getHeight(), o1.getHeight()));
        map.put(new Student("蜘蛛精", 25, 168.5), "盘丝洞");
        map.put(new Student("蜘蛛精", 25, 168.5), "水帘洞");
        map.put(new Student("至尊宝", 23, 163.5), "水帘洞");
        map.put(new Student("牛魔王", 28, 183.5), "牛头山");
        System.out.println(map);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到