Java基础知识之TreeMap的使用

一、TreeMap的介绍

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的基本操作代码 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);
    }

运行结果:
Java基础知识之TreeMap的使用_第1张图片


接下来我们探讨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值重复则不会带来任何影响

Java基础知识之TreeMap的使用_第2张图片


三、TreeMap的遍历操作 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);
        }
    }

运行结果:

Java基础知识之TreeMap的使用_第3张图片


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());
        }
    }

运行结果:

Java基础知识之TreeMap的使用_第4张图片


四、TreeMap集合遍历输出自定义学生对象并遍历bug 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的方法
Java基础知识之TreeMap的使用_第5张图片


注意:在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);
        }
    }

运行结果:(成功输出!!!)
Java基础知识之TreeMap的使用_第6张图片


②在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);
        }

    }

运行结果:(成功输出!!!)
Java基础知识之TreeMap的使用_第7张图片


OK!!!结束!!!

你可能感兴趣的:(Java基础知识总结,java,jvm,servlet)