1、整体架构
首先在Java中的Map是一个接口,位于最上层
HashMap的特点:
- 无序
- 唯一
这两个特点是按照key进行总结的,因为底层key遵循哈希表的结构(数组 + 链表)
哈希表的原理:比如放入这个集合的数据对应的那个类:必须重写hashCode方法和equals方法。
Hashtable的特点
Hashtable也包含HashMap的上述两个特点。
Hashtable与HashMap的区别:
HashMap,JDK1.2才有的,线程不安全的,key可以存入null值并且key的null值也是遵循唯一的特点
Hashtable,JDK1.0就有了,线程安全的,key不可以存入null值
LinkeHashMap的特点
底层:哈希表 + 链表(用链表起到按照输入顺序进行输出的作用)
特点: 唯一,有序
(按照输入的顺序进行输出)
TreeMap的特点
特点:唯一、有序(按照升序或者降序)
原理:二叉树,key遵照二叉树的特点,放入集合的key的数据对应的类型内部一定呀实现比较器(外部比较器、内部比较器二选一)
TreeMap与另外的三个Map判断是否是相同的key值时候是不一样的,直接上代码:
首先定义一个Student类
package com.sk.javase.bean;
import java.util.Objects;
/**
* @author: create by sunkuan
* @Description:
* @date: 2022/7/17 - 16:37
*/
public class Student implements Comparable<Student>{
private int age;
private String name;
private double height;
public Student(int age, String name, double height) {
this.age = age;
this.name = name;
this.height = height;
}
@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 && Double.compare(student.height, height) == 0 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name, height);
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
// if(this.age == o.age){
// return this.name.compareTo(o.name);
// }else {
// return this.age - o.age;
// }
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", height=" + height +
'}';
}
}
对于HashMap的情况:
package com.sk.javase.map.treemap;
import com.sk.javase.bean.Student;
import java.util.HashMap;
import java.util.Map;
/**
* @author: create by sunkuan
* @Description:
* @date: 2022/7/17 - 16:41
*/
public class HashMapDemo {
public static void main(String[] args) {
Map<Student, Integer> studentHashMap = new HashMap<>();
System.out.println(studentHashMap.put(new Student(20, "wangwu", 160), 1003));
System.out.println(studentHashMap.put(new Student(19, "lisi", 160), 1002));
System.out.println(studentHashMap.put(new Student(20, "zhangsan", 160), 1001));
System.out.println(studentHashMap.put(new Student(18, "zhangsan", 160), 1004));
System.out.println(studentHashMap.put(new Student(34, "zhaoliu", 189), 1005));
System.out.println(studentHashMap.put(new Student(20, "wangwu", 160), 1009));
System.out.println(studentHashMap.size());
System.out.println(studentHashMap);
}
}
输出的结果如下:
null
null
null
null
null
1003
5
{Student{age=20, name='zhangsan', height=160.0}=1001, Student{age=34, name='zhaoliu', height=189.0}=1005, Student{age=18, name='zhangsan', height=160.0}=1004, Student{age=19, name='lisi', height=160.0}=1002, Student{age=20, name='wangwu', height=160.0}=1009}
一共往hashMap中放入了6个Student对象,但是实际只成功放入了5个Student对象,放入的时候会使用到hashCode和equals方法,因为 new Student(20, “wangwu”, 160) 有两个,他们的hashCode和equals相等,所以放入第二个new Student(20, “wangwu”, 160) 对象的时候认为放入了相同的key,则保留前者的key和后者的value。
对于TreeMap的情况:
Student类还使用上一个
package com.sk.javase.map.treemap;
import com.sk.javase.bean.Student;
import java.util.Map;
import java.util.TreeMap;
/**
* @author: create by sunkuan
* @Description:
* @date: 2022/7/17 - 16:41
*/
public class TreeMapDemo {
public static void main(String[] args) {
Map<Student, Integer> studentTreeMap = new TreeMap<>();
System.out.println(studentTreeMap.put(new Student(20, "wangwu", 160), 1003));
System.out.println(studentTreeMap.put(new Student(19, "lisi", 160), 1002));
System.out.println(studentTreeMap.put(new Student(20, "zhangsan", 160), 1001));
System.out.println(studentTreeMap.put(new Student(18, "zhangsan", 160), 1004));
System.out.println(studentTreeMap.put(new Student(34, "zhaoliu", 189), 1005));
System.out.println(studentTreeMap.size());
System.out.println(studentTreeMap);
}
}
运行的结果是:
null
null
1003
null
null
4
{Student{age=18, name='zhangsan', height=160.0}=1004, Student{age=19, name='lisi', height=160.0}=1002, Student{age=20, name='wangwu', height=160.0}=1001, Student{age=34, name='zhaoliu', height=189.0}=1005}
现象:一共往treeMap中放入了5个Student对象,但是实际只成功放入了4个Student对象,为什么我也没放入两个hashCode和equals方法都相同的两个Student对象,结果放入的对象少了一个,原来是这样的,treeMap判断放入的key值是否相等,是通过外部比较器中的compare方法或者内部比较器中的compareTo方法来判断的。而我没有外部比较器,只有一个Student类中的内部比较器,并且内部比较器中只比较了Student的年龄,也就说只要两个Student对象的年龄相等TreeMap就认为是同一个key值,即TreeMap认为new Student(20, “wangwu”, 160)和new Student(20, “zhangsan”, 160)属于同一个key。对于TreeMap有一个特点,若重复存储相同的Key值,则保留前者的Key和后者的Value(而非后者的Key和后者的Value),所以保留了前者的key值new Student(20, “wangwu”, 160),和后者的value即1001。
结论:TreeMap判断放入的key值是否相等,是通过外部比较器中的compare方法或者内部比较器中的compareTo方法来判断的而不是用hashCode和equals方法。
整体总结:对于上述的所有Map来说,若重复存储相同的Key值,则保留前者的Key和后者的Value(而非后者的Key和后者的Value),而在判断是否是相同的key值时候,TreeMap与其他三者不一样。其他三者判断是否是同一个key值,是通过hashCode和equals方法比较的,而TreeMap是用外部比较器中的compare方法或者内部比较器中的compareTo方法决定的。
推荐阅读:
JDK1.8新特性-函数式接口以及Lambda表达式
JDK1.8新特性之-Stream流
java中try catch finally的语法
mysql8.0.17数据库的搭建-windows
Centos7下安装PostgreSQL11
SparkCore学习
如果有写的不对的地方,欢迎大家指正,如果有什么疑问,可以直接私信我