TreeMap是NavigableMap接口的一个实现类(而HashMap实现的是Map的接口),但是同样的TreeMap具有Map的特点。TreeMap的底层是红黑树结构。
Map是用于保存具有映射关系的数据集合,它具有双列存储的特点,即一次必须添加两个元素,即一组键值对==>
,其中Key的值不可重复(当Key的值重复的时候,后面插入的对象会将之前插入的具有相同的Key值的对象覆盖掉),Value的值可重复。
其中
键值对在Java语言中又被称之为Entry/entry,Map.Entry就相当于Student.name,若name的数据类型为String,则Student.name的数据类型为String,同理若 中key的数据类型为Integer,value的数据类型为String,则Map.Entry的数据类型为 。在HashMap与TreeMap中均可使用Map.Entry。
接下来我们将结合代码来具体学习TreeTreeMap相关知识。
TreeMap入门
Key数据类型为Integer类型,Value数据类型为String类型的TreeMap
public static void main(String[] args) {
//创建一个Key为Integer数据类型,Value为String数据类型的treeMap
//若要使用TreeMap,则需要导入import java.util.TreeMap;
TreeMap<Integer,String> treeMap=new TreeMap<>();
//使用put()方法添加元素
treeMap.put(18,"xiaoming");//第一对象
treeMap.put(19,"xiaoming");//第二对象
treeMap.put(20,"wangwu");//第三对象
//普通打印
System.out.println(treeMap);
}
接下来我们探讨Key的值不可重复(当Key的值重复的时候,后面插入的对象会将之前插入的具有相同的Key值的对象覆盖掉),Value的值可重复此问题
Key数据类型为Integer类型,Value数据类型为String类型的Map
其中第一对象和第二对象的Value值相同,第三对象与第四对象的Key值相同。
public static void main(String[] args) {
//创建一个Key为Integer数据类型,Value为String数据类型的treeMap
//若要使用TreeMap,则需要导入import java.util.TreeMap;
TreeMap<Integer,String> treeMap=new TreeMap<>();
//使用put()方法添加元素
treeMap.put(18,"xiaoming");//第一对象
treeMap.put(19,"xiaoming");//第二对象
treeMap.put(20,"wangwu");//第三对象
treeMap.put(20,"lisi");//第四对象
//普通打印
System.out.println(treeMap);
}
运行结果:(我们发现后面插入的第四对象将之前插入的第三对象给覆盖掉了,而第一对象与第二对象的Value值重复则不会带来任何影响)
TreeMap基础
TreeMap的遍历分为调用keySet()方法遍历和entrySet()方法遍历
TreeMap调用keySet()方法遍历
public static void main(String[] args) {
//创建一个Key为Integer数据类型,Value为String数据类型的treeMap
//若要使用TreeMap,则需要导入import java.util.TreeMap;
TreeMap<Integer,String> treeMap=new TreeMap<>();
//使用put()方法添加元素
treeMap.put(18,"xiaoming");//第一对象
treeMap.put(19,"xiaoming");//第二对象
treeMap.put(20,"wangwu");//第三对象
//调用keySet()方法遍历
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//调用keySet()方法,Set<>泛型约束应与Key的数据类型一致
//例如在本代码中,TreeMap,Key的数据类型为Integer,因此Set<>泛型约束也应当为Integer
//Set set=treeMap.keySet();代码的意思为将TreeMap中所有Key值存入Set集合(18,19,20)
//那么set即为Key值集合
Set<Integer> set=treeMap.keySet();
//使用forEach()语句遍历,Integer为set的数据类型,i为set的复用名(相当于set)
//那么i就成为了Key值
for(Integer i:set){
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//接下来我们要根据Key值来查找各个Key值对应的Value值
//Value数据类型为String,设置一个String变量str来存储Value
//treeMap.get(i);代码意思为根据i(Key值)找到相对应的Value值
String str=treeMap.get(i);
//打印输出
System.out.println("Key的值为:"+i+" "+"Value的值为:"+str);
}
}
运行结果:
TreeMap调用entrySet()方法遍历
public static void main(String[] args) {
//若要使用TreeMap,我们需要导入import java.util.TreeMap;
//创建一个TreeMap空参构造器(new TreeMap<>()此即为引用空参构造创建一个对象),同时使用泛型来约束treeMap的数据类型,Key的数据类型为Integer,Value的数据类型为String
TreeMap<Integer,String> treeMap=new TreeMap<>();
//通过put()方法来添加数据
treeMap.put(18,"xiaoming");
treeMap.put(19,"xiaoming");
treeMap.put(20,"wangwu");
//TreeMap通过调用entrySet()方法遍历
//这时我们需要导入Map的包:import java.util.Map;和Set的包:import java.util.Set;
//调用entrySet()方法,Set<>泛型约束应与Map.Entry的数据类型一致,即
//键值对,在Java语言中又被称之为Entry/entry,Map.Entry就相当于Student.name,若name的数据类型为String,则Student.name的数据类型为String,同理若中key的数据类型为Integer,value的数据类型为String,则Map.Entry的数据类型为,在这里就是。
//Set> set=treeMap.entrySet();代码的意思为将TreeMap中所有(Key,Value)值存入Set集合[(18,"xiaoming"),(19,“xiaoming”),(20,“wangwu”)]
//那么set即为(Key,Value)值集合
Set<Map.Entry<Integer,String>> set=treeMap.entrySet();
//使用forEach()语句遍历,Integer为set的数据类型,i为set的复用名(相当于set)
//那么i就成为了(Key,Value)值
for(Map.Entry<Integer,String> i:set){
//打印输出,直接调用getKey()方法得到Key值,直接调用getValue()得到Value值
System.out.println("Key的值为:"+i.getKey()+" "+"Value的值为:"+i.getValue());
}
}
运行结果:
TreeMap自定义数据类型输出bug
需求:创建一个Map集合,Key键是学生对象(Student),Value值是籍贯(String)。
要求:存储三个键值对元素(Entry),遍历,并按学生年龄排序遍历,若年龄相同则按姓名排序。
原始Student1类
public class Student1 {
private String name;
private int age;
public Student1() {
}
public Student1(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 "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
TreeMap遍历输出bug
public static void main(String[] args) {
//若要使用TreeMap,我们需要导入import java.util.TreeMap;
//创建一个TreeMap空参构造器(new TreeMap<>()此即为引用空参构造创建一个对象),同时使用泛型来约束treeMap的数据类型,Key的数据类型为Student1,Value的数据类型为String
TreeMap<Student1,String> treeMap=new TreeMap<>();
//创建Student1对象
Student1 student=new Student1("zhangsan",18);
Student1 student1=new Student1("lisi",19);
Student1 student2=new Student1("wangwu",20);
Student1 student3=new Student1("zhaoliu",18);
通过put()方法来添加数据
treeMap.put(student,"北京");
treeMap.put(student1,"深圳");
treeMap.put(student2,"上海");
treeMap.put(student3,"广州");
//调用keySet方法遍历
//这时我们需要导入Set的包:import java.util.Set;
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//调用keySet()方法,Set<>泛型约束应与Key的数据类型一致
//例如在本代码中,TreeMap,Key的数据类型为Student1,因此Set<>泛型约束也应当为Integer
//Set set=treeMap.keySet();代码的意思为将treeMap中所有Key值存入Set集合(student,student1,student2,student3)
//那么set即为Key值集合
Set<Student1> set=treeMap.keySet();
//使用forEach()语句遍历,Student1为set数据类型,i为set的复用名(相当于set)
//那么i就成为了Key值
for(Student1 stu:set){
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//接下来我们要根据Key值来查找各个Key值对应的Value值
//Value数据类型为String,设置一个String变量来存储Value
//treeMap.get(i);代码意思为根据i(Key值)找到相对应的Value值
String str=treeMap.get(stu);
//打印输出
System.out.println("Key的值为:"+stu+" "+"Value的值为:"+str);
}
}
运行结果:(我们发现出现了bug,bug显示的信息是Student1类没有重写Comparable的方法)
注意:在TreeMap或者TreeSet中遍历输出自定义类时,如果我们想要它可以正常输出,有两种方法:①在自定义类中重写Comparable中的compareTo()方法②在main方法中的TreeMap或者TreeSet构造器中编写匿名内部类并重写compareTo()方法。
①在自定义类中重写Comparable中的compareTo()方法
重写了Comparable中的compareTo()方法的Student1类
public class Student1 implements Comparable<Student1>{
private String name;
private int age;
@Override
public int compareTo(Student1 o) {
//在这里我们定义排序规则:主要根据age进行排序
/**
* 例如我们首先插入了一个("zhangsan",18),那么毫无疑问它会排在第一位
* 然后我们插入("lisi",19),那么此时this.age=18;o.getAge()=19,那么("lisi",19)就要插入到("zhangsan",18)之后
* 随后我们插入("zhaoliu",19),那么它会先于("zhangsan",18).age进行比较,那么("zhaoliu",19)就要插入到("zhangsan",18)后面,之后它再与("lisi",19).age进行比较,age相同,比较name,zhaoliu排在lisi之后
* 因此最后排序结果为("zhangsan",18),("lisi",19),("zhaoliu",19)
* */
int result=this.getAge()-o.getAge();
//如果两个对象的年龄相同,我们再根据姓名进行排序
result=result==0?this.getName().compareTo(o.getName()):result;
return result;
}
public Student1() {
}
public Student1(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 "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
TreeMap遍历输出
public static void main(String[] args) {
//若要使用TreeMap,我们需要导入import java.util.TreeMap;
//创建一个TreeMap空参构造器(new TreeMap<>()此即为引用空参构造创建一个对象),同时使用泛型来约束treeMap的数据类型,Key的数据类型为Student1,Value的数据类型为String
TreeMap<Student1,String> treeMap=new TreeMap<>();
//创建Student1对象
Student1 student=new Student1("zhangsan",18);
Student1 student1=new Student1("lisi",19);
Student1 student2=new Student1("wangwu",20);
Student1 student3=new Student1("zhaoliu",18);
通过put()方法来添加数据
treeMap.put(student,"北京");
treeMap.put(student1,"深圳");
treeMap.put(student2,"上海");
treeMap.put(student3,"广州");
//调用keySet方法遍历
//这时我们需要导入Set的包:import java.util.Set;
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//调用keySet()方法,Set<>泛型约束应与Key的数据类型一致
//例如在本代码中,TreeMap,Key的数据类型为Student1,因此Set<>泛型约束也应当为Integer
//Set set=treeMap.keySet();代码的意思为将treeMap中所有Key值存入Set集合(student,student1,student2,student3)
//那么set即为Key值集合
Set<Student1> set=treeMap.keySet();
//使用forEach()语句遍历,Student1为set数据类型,i为set的复用名(相当于set)
//那么i就成为了Key值
for(Student1 stu:set){
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//接下来我们要根据Key值来查找各个Key值对应的Value值
//Value数据类型为String,设置一个String变量来存储Value
//treeMap.get(i);代码意思为根据i(Key值)找到相对应的Value值
String str=treeMap.get(stu);
//打印输出
System.out.println("Key的值为:"+stu+" "+"Value的值为:"+str);
}
}
②在main方法中的TreeMap构造器中编写匿名内部类并重写compareTo()方法。
原始Student1类
public class Student1{
private String name;
private int age;
public Student1() {
}
public Student1(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 "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
在main方法中的TreeMap构造器中编写匿名内部类并重写compareTo()方法的TreeMap遍历输出
public static void main(String[] args) {
//若要使用TreeMap,我们需要导入import java.util.TreeMap;
//创建一个TreeMap空参构造器(new TreeMap<>()此即为引用空参构造创建一个对象),同时使用泛型来约束treeMap的数据类型,Key的数据类型为Student1,Value的数据类型为String
TreeMap<Student1,String> treeMap=new TreeMap<>(new Comparator<Student1>() {
@Override
public int compare(Student1 o1, Student1 o2) {
//在这里我们定义排序规则:主要根据age进行排序
/**
* 例如我们首先插入了一个("zhangsan",18),那么毫无疑问它会排在第一位
* 然后我们插入("lisi",19),那么此时o1.getAge()=18;o2.getAge()=19,那么("lisi",19)就要插入到("zhangsan",18)之后
* 随后我们插入("zhaoliu",19),那么它会先于("zhangsan",18).getAge()进行比较,那么("zhaoliu",19)就要插入到("zhangsan",18)后面,之后它再与("lisi",19).getAge()进行比较,age相同,比较name,zhaoliu排在lisi之后
* 因此最后排序结果为("zhangsan",18),("lisi",19),("zhaoliu",19)
* */
int result=o1.getAge()-o2.getAge();
//如果两个对象的年龄相同,我们再根据姓名进行排序
result= result==0 ? o1.getName().compareTo(o2.getName()) : result;
return result;
}
});
//创建Student1对象
Student1 student=new Student1("zhangsan",18);
Student1 student1=new Student1("lisi",19);
Student1 student2=new Student1("wangwu",20);
Student1 student3=new Student1("zhaoliu",18);
通过put()方法来添加数据
treeMap.put(student,"北京");
treeMap.put(student1,"深圳");
treeMap.put(student2,"上海");
treeMap.put(student3,"广州");
//调用keySet方法遍历
//这时我们需要导入Set的包:import java.util.Set;
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//调用keySet()方法,Set<>泛型约束应与Key的数据类型一致
//例如在本代码中,TreeMap,Key的数据类型为Student1,因此Set<>泛型约束也应当为Integer
//Set set=treeMap.keySet();代码的意思为将treeMap中所有Key值存入Set集合(student,student1,student2,student3)
//那么set即为Key值集合
Set<Student1> set=treeMap.keySet();
//使用forEach()语句遍历,Student1为set数据类型,i为set的复用名(相当于set)
//那么i就成为了Key值
for(Student1 stu:set){
//在TreeMap遍历中Key占据着主导地位,可以通过Key值找到对应的Value值
//接下来我们要根据Key值来查找各个Key值对应的Value值
//Value数据类型为String,设置一个String变量来存储Value
//treeMap.get(i);代码意思为根据i(Key值)找到相对应的Value值
String str=treeMap.get(stu);
//打印输出
System.out.println("Key的值为:"+stu+" "+"Value的值为:"+str);
}
}
OK!!!结束!!!