JavaSE学习笔记 Map接口的具体实现类:LinkedHashMap以及TreeMap

Map集合接口具体实现类:LinkedHashMap以及TreeMap

前面我们学习了Map接口中最常用的实现类:HashMap,并且对HashMap的底层实现原理做了一定的深入探讨。下面我们将要了解的是Map接口中的另外两大实现类:LinkedHashMap与TreeMap。

1.LinkedHashMap的概述

LinkedHashMap实现了Map接口,而且继承自HashMap。
它的多种操作都是建立在HashMap的操作基础上的。

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>

同HashMap不同的是,LinkedHashMap维护了一个Entry的双向链表,保证了插入Entry中的顺序。
JavaSE学习笔记               Map接口的具体实现类:LinkedHashMap以及TreeMap
如上图所示,加入顺序为key1,key2,key3,key4,就会维护上面红线所示的双向链表。

  • 为实现双向链表,LinkedHashMap底层源码这样进行设置:
//LinkedHashMap中的node直接继承自HashMap中的Node。并且增加了双向的指针
static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

由上面源码中设置可知,LinkedHashMap 键的数据结构是 链表和哈希表,链表保证了键有序,哈希表保证了键唯一。

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;

public class MyTest {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        //LinkedHashMap 键的数据结构是 链表和哈希表,链表保证了键有序,哈希表保证了键唯一
        map.put("s001", "张三");
        map.put("s001", "张三丰");
        map.put("s002", "李四");
        map.put("s003", "王五");
        map.put("s004", "陈六");

        //遍历LinkedHashMap方式一
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            String value = map.get(key);
            System.out.println(key+"======="+value);
        }
        System.out.println("============");

        //遍历LinkedHashMap方式二
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"==="+value);
        }
        System.out.println("=============");

        //遍历LinkedHashMap方式三
        map.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String key, String value) {
                System.out.println(key+"===="+value);
            }
        });
    }
}

LinkedHashMap相对于HashMap而言,它继承了HashMap,仅仅重写了几个方法,以改变它迭代遍历时的顺序。


2.TreeMap概述

TreeMap的数据结构为红黑树,可以保证键的排序性和唯一性。排序分为自然排序与比较器排序。TreeMap线程不安全,并且效率比较高。

案例演示:TreeMap集合键是Integer,值是String类型

public class MyTest2 {
    public static void main(String[] args) {
        TreeMap<Integer, String> treemap = new TreeMap<>();

        treemap.put(15,"张三");
        treemap.put(10,"李四");
        treemap.put(13,"王五");
        treemap.put(14,"陈六");
        treemap.put(11,"刘七");
        treemap.put(12,"赵八");

        System.out.println(treemap);
    }
}

TreeMap是双列集合,双列集合的键需要保持唯一,在此例中Intege类中源码实现Compareable接口,重写了CompareTo()方法。

运行后的结果为:

JavaSE学习笔记               Map接口的具体实现类:LinkedHashMap以及TreeMap

案例演示2:TreeMap集合键是Student,值是String类型的案例,按照Student类中的属性年龄的大小进行排序。

  • 方式一:自然排序
//自定义类:Student类
//自然排序,实现Compareable接口,重写CompareTo方法
public class Student  implements Comparable<Student>{
    private String name;
    private int age;

    public Student() {
    }

    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 boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

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

    @Override
    public int compareTo(Student stu) {
        //比较年龄大小
        int num = age-stu.age;
        //如果年龄相同,比较姓名内容是否相同
        int num1=num==0?name.compareTo(stu.name):num;

        return num1;

    }
}


//测试类
import java.util.TreeMap;
public class MyTest3 {
    public static void main(String[] args) {
        TreeMap<Student, String> treemap = new TreeMap<>();

        treemap.put(new Student("张三",23),"s001");
        treemap.put(new Student("李四",24),"s002");
        treemap.put(new Student("王五",25),"s003");
        treemap.put(new Student("陈六",23),"s004");

        System.out.println(treemap);
    }
}

运行后的结果为:
JavaSE学习笔记               Map接口的具体实现类:LinkedHashMap以及TreeMap


  • 方案二:比较器排序
//自定义的Student类
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    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 boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

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

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


    }
    }


import java.util.Comparator;
import java.util.TreeMap;

public class MyTest {
    public static void main(String[] args) {
        TreeMap<Student, String> treemap = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //比较年龄大小
                int num = s1.getAge() - s2.getAge();
                //当年龄相同时,比较姓名内容是否相等
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });


        treemap.put(new Student("张三",23),"s001");
        treemap.put(new Student("李四",24),"s002");
        treemap.put(new Student("王五",25),"s003");
        treemap.put(new Student("陈六",23),"s004");

        System.out.println(treemap);


    }
}


运行后的结果为:
JavaSE学习笔记               Map接口的具体实现类:LinkedHashMap以及TreeMap


总结

本节主要介绍了LinkedHashMap以及TreeMap的使用,其中需要了解LinkedHashMap与HashMap的区别:LinkedHashMap相对于HashMap而言,它继承了HashMap,仅仅重写了几个方法,以改变它迭代遍历时的顺序。TreeMap则重点掌握排序的两种方式:自然排序与比较器排序。

JavaSE学习笔记               Map接口的具体实现类:LinkedHashMap以及TreeMap

上一篇:react-antd-input-onPressEnter


下一篇:javascript – 为什么第一个将它视为布尔值而第二个不是?