java:Map系列集合 - HashMap、LinkedHashMap、TreeMap的底层原理

Map系列集合常用到的:

在这里插入图片描述

  • HashMap:无序、键不重复、无索引。
  • LinkedHashMap:有序、键不重复、无索引。
  • TreeMap:按照键的大小默认升序排序、键不重复、无索引。

HashMap集合

底层原理

  • HashMap是基于哈希表实现的。哈希表是一种增删改查性能都较好的数据结构。
  • 在JDK8之前,哈希表=数组+链表
  • 从JDK8开始,哈希表=数组+链表+红黑树
  • HashMap是无序、键不重复、无索引的。
  • HashMap键依赖于hashCode方法和equals方法来保证唯一。
  • 如果键存储的是自定义类型的对象,可以重写hashCode方法和equals方法,这样可以确保对于内容相同的多个对象,HashMap集合认为是重复的。

示例:作为HashMap键的自定义对象重写了hashCode方法和equals方法

定义一个Student类,它重写了hashCode方法和equals方法,这样可以确保对于内容相同的多个对象,HashMap集合认为是重复的:

package com.team.map;

import java.util.Objects;

public class Student {

    private String name;
    private double score;

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Double.compare(score, student.score) == 0 && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, score);
    }
}

定义测试类:

package com.team.map;


import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        Map<Student, String> map = new HashMap<>();
        map.put(new Student("张三", 65.5), "1班");
        map.put(new Student("张三", 65.5), "2班");
        map.put(new Student("李四", 78), "2班");
        map.put(new Student("王五", 90), "1班");
        System.out.println(map);
    }
}

运行输出:

{Student{name='李四', score=78.0}=2, Student{name='张三', score=65.5}=2, Student{name='王五', score=90.0}=1}

LinkedHashMap集合

LinkedHashMap:有序、键不重复、无索引。

底层原理

  • LinkedHashMap底层是仍然基于哈希表实现的,只不过每个键值对元素又额外多了一个双向链表的机制用来记录元素的顺序。

示例:LinkedHashMap集合是有序、键不重复的

package com.team.map;


import java.util.LinkedHashMap;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        Map<String, Integer> map = new LinkedHashMap<>();
        map.put("张三", 60);
        map.put("张三", 65);
        map.put("李四", 50);
        map.put("王五", 80);
        map.put("马六", 40);

        System.out.println(map);
    }
}

运行输出:

{张三=65, 李四=50, 王五=80, 马六=40}

TreeMap集合

TreeMap:按照键的大小默认升序排序、键不重复、无索引。

底层原理

  • TreeMap是基于红黑树实现的排序。

如果TreeMap集合的键是自定义类型的对象,那么支持两种方式来指定排序规则

  • 方式一:让自定义类实现Comparable接口,指定比较规则。
  • 方式二:使用TreeMap的有参构造器public TreeMap(Comparator<? super K> comparator),在传参的时候创建Comparator比较器对象,用来指定比较规则。

示例:TreeMap集合的键是自定义类型的对象,自定义类实现Comparable接口,指定比较规则

自定义Student类,实现了Comparable接口:

package com.team.map;

public class Student implements Comparable<Student> {

    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}

定义测试类:

package com.team.map;

import java.util.Map;
import java.util.TreeMap;

public class Test {

    public static void main(String[] args) {
        Map<Student, String> map = new TreeMap<>();
        map.put(new Student("张三", 22), "1班");
        map.put(new Student("李四", 20), "2班");
        map.put(new Student("王五", 19), "2班");
        map.put(new Student("马六", 18), "1班");

        System.out.println(map);
    }
}

运行输出:

{Student{name='马六', age=18}=1, Student{name='王五', age=19}=2, Student{name='李四', age=20}=2, Student{name='张三', age=22}=1}

示例:使用TreeMap的有参构造器public TreeMap(Comparator<? super K> comparator)

定义Student类:

package com.team.map;

public class Student {

    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

定义测试类:

package com.team.map;

import java.util.Map;
import java.util.TreeMap;

public class Test {

    public static void main(String[] args) {
        Map<Student, String> map = new TreeMap<>((o1, o2) -> o1.getAge() - o2.getAge());
        map.put(new Student("张三", 22), "1班");
        map.put(new Student("李四", 20), "2班");
        map.put(new Student("王五", 19), "2班");
        map.put(new Student("马六", 18), "1班");

        System.out.println(map);
    }
}

运行输出:

{Student{name='马六', age=18}=1, Student{name='王五', age=19}=2, Student{name='李四', age=20}=2, Student{name='张三', age=22}=1}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值