Java进阶: 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

时间:2024-01-27 19:49:20

 

                    ==知识点==

  1. 红黑树

  2. HashSet

  3. Map

  4. HashMap

  5. TreeMap

                   ==知识点梳理==

1.红黑树

1.1红黑树-概述【了解】

1.什么是红黑树

平衡二叉B树,每一个节点可以是红或者黑,红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的。

 

 

 

 

1.2 红黑树-红黑规则 (了解) 

  • 红黑树的红黑规则有哪些

    1. 每一个节点或是红色的,或者是黑色的

    2. 根节点必须是黑色

    3. 所有叶子节点(空的节点被称作叶子节点)都是黑色的

    4. 不能出现两个红色节点相连 的情况

    5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

       

       

       

1.3 红黑树-添加节点的默认颜色(了解) 

添加节点时,默认为红色,效率高

1.4 红黑树-添加节点后,如何保证红黑规则1 【难点】

 

 

 

 

 

1.5 红黑树-添加节点后,如何保证红黑规则2 【难点】

(旋转之后,根据规则验证是否是红黑树,总结红黑树添加节点的规则)

 

 

 

 

 

1.6 红黑树练习-成绩排序案例【重点】

(共3点)

1.案例需求

  • 用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩,英语成绩),并遍历该集合

  • 要求: 按照总分从低到高排序

代码实现

学生类

public class Student implements Comparable<Student> {
   private String name;
   private int chinese;
   private int math;
   private int english;

   public Student() {
  }

   public Student(String name, int chinese, int math, int english) {
       this.name = name;
       this.chinese = chinese;
       this.math = math;
       this.english = english;
  }

   public String getName() {
       return name;
  }

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

   public int getChinese() {
       return chinese;
  }

   public void setChinese(int chinese) {
       this.chinese = chinese;
  }

   public int getMath() {
       return math;
  }

   public void setMath(int math) {
       this.math = math;
  }

   public int getEnglish() {
       return english;
  }

   public void setEnglish(int english) {
       this.english = english;
  }

   public int getSum() {
       return this.chinese + this.math + this.english;
  }

   @Override
   public int compareTo(Student o) {
       // 主要条件: 按照总分进行排序
       int result = o.getSum() - this.getSum();
       // 次要条件: 如果总分一样,就按照语文成绩排序
       result = result == 0 ? o.getChinese() - this.getChinese() : result;
       // 如果语文成绩也一样,就按照数学成绩排序
       result = result == 0 ? o.getMath() - this.getMath() : result;
       // 如果总分一样,各科成绩也都一样,就按照姓名排序
       result = result == 0 ? o.getName().compareTo(this.getName()) : result;
       return result;
  }
}

测试类

public class TreeSetDemo {
   public static void main(String[] args) {
       //创建TreeSet集合对象,通过比较器排序进行排序
       TreeSet<Student> ts = new TreeSet<Student>();
       //创建学生对象
       Student s1 = new Student("jack", 98, 100, 95);
       Student s2 = new Student("rose", 95, 95, 95);
       Student s3 = new Student("sam", 100, 93, 98);
       //把学生对象添加到集合
       ts.add(s1);
       ts.add(s2);
       ts.add(s3);

       //遍历集合
       for (Student s : ts) {
           System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getEnglish() + "," + s.getSum());
      }
  }
}

2.TreeSet原理

 

 

 

 

2.HashSet集合

2.1HashSet-基本使用【重点】

1.什么是HashSet(HashSet的特点)

  • 底层数据结构是哈希表

  • 存取无序

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历(get方法)

2.HashSet使用-存储字符串并遍历

package com.itheima.myhashset;

import java.util.HashSet;
import java.util.Iterator;

/**
* 添加字符串并进行遍历
*/
public class HashSetDemo1 {
   public static void main(String[] args) {
       HashSet<String> hs = new HashSet<>();

       hs.add("hello");
       hs.add("world");
       hs.add("java");
       hs.add("java");
       hs.add("java");
       hs.add("java");
       hs.add("java");
       hs.add("java");

       Iterator<String> it = hs.iterator();
       while(it.hasNext()){
           String s = it.next();
           System.out.println(s);
      }
       System.out.println("=============================");

       for (String s : hs) {
           System.out.println(s);
      }
  }
}

2.2哈希值【了解】

1.什么是哈希值

是JDK根据对象的地址或者属性值,算出来的int类型的整数

2.如何获取对象中的Hash值

Object类中有一个方法: public int hashCode():根据对象的地址值计算出来的哈希值

3.哈希值的特点

  • 没有重写HashCode的情况:

1.同种一对象多次调用hashCode方法返回值是一样的

2.不同对象hashCode方法返回值不一样

  • Object子类重写hashCode方法的情况:

重写的目的是计算对象哈希值时,按属性值来计算,因此只要属性值相同,不同对象的hashCode方法返回值是一样的

package com.itheima.myhashset;

/**
* 计算哈希值
*/
public class HashSetDemo2 {
   public static void main(String[] args) {
       Student s1 = new Student("xiaozhi",23);
       Student s2 = new Student("xiaomei",22);

       //因为在Object类中,是根据对象的地址值计算出来的哈希值。
       System.out.println(s1.hashCode());//1060830840
       System.out.println(s1.hashCode());//1060830840


       System.out.println(s2.hashCode());//2137211482
  }
}

Student类

package com.itheima.myhashset;

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

   //我们可以对Object类中的hashCode方法进行重写
   //在重写之后,就一般是根据对象的属性值来计算哈希值的。
   //此时跟对象的地址值就没有任何关系了。
   @Override
   public int hashCode() {
       int result = name != null ? name.hashCode() : 0;
       result = 31 * result + age;
       return result;
  }

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

2.4HashSet-JDK7底层原理【难点】

哈希表=数组 + 链表

 

 

2.5HashSet-JDK8底层优化【难点】

(共两点)

1.HashSet 在JDK1.8之后的原理

  • 节点个数少于等于8个

    数组 + 链表

  • 节点个数多于8个

    数组 + 红黑树

 

 

2.HashSet 在JDK1.8版本的存储流程

 

 

 

 

 

 

 

2.6HashSet集合存储学生对象并遍历【重点】

  • 案例需求

    • 创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合

    • 要求:学生对象的成员变量值相同,我们就认为是同一个对象

  • 代码实现

    测试类

    public class HashSetDemo2 {
       public static void main(String[] args) {
           //HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法
           HashSet<Student> hashSet = new HashSet<>();
           Student s1 = new Student("xiaohei",23);
           Student s2 = new Student("xiaohei",23);
           Student s3 = new Student("xiaomei",22);
           hashSet.add(s1);
           hashSet.add(s2);
           hashSet.add(s3);
           for (Student student : hashSet) {
               System.out.println(student);
          }
      }
    }

    学生类

    package com.itheima.myhashset;

    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;

           if (age != student.age) {
               return false;
          }
           return name != null ? name.equals(student.name) : student.name == null;
      }


       //我们可以对Object类中的hashCode方法进行重写
       //在重写之后,就一般是根据对象的属性值来计算哈希值的。
       //此时跟对象的地址值就没有任何关系了。
       @Override
       public int hashCode() {
           int result = name != null ? name.hashCode() : 0;
           result = 31 * result + age;
           return result;
      }

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

     

3.Map集合

3.1Map-基本使用【重点、难点】

(共3点)

1.什么是Map集合【记忆】

Map集合又称为双列集合,双列集合中元素的内容是成对的

2.Map集合的特点 【记忆】

键不能重复,值可以重复

键与值之间是一一对应的关系

(键+值)这个整体我们称之为"键值对"或"键值对对象",在Java中又叫"Entry对象"

 

 

3.如何使用Map集合

1.Map集合格式

interface Map<K,V>  K:键的类型;V:值的类型

2.如何创建Map集合对象

Map<String,String> map = new HashMap<String,String>();//使用具体实现类,采用多态形式创建

4.使用Map集合存储学生学号和姓名

package com.itheima.mapdemo1;

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

/**
* Map的基本使用
*/
public class MyMap1 {
   public static void main(String[] args) {
       Map<String,String> map = new HashMap<>();

       //map.add();
       map.put("itheima001","小智");
       map.put("itheima002","小美");
       map.put("itheima003","大胖");

       System.out.println(map);
  }
}

3.2Map常用方法【重点】

  • 方法介绍

    方法名说明
    V put(K key,V value) 添加元素
    V remove(Object key) 根据键删除键值对元素
    void clear() 移除所有的键值对元素
    boolean containsKey(Object key) 判断集合是否包含指定的键
    boolean containsValue(Object value) 判断集合是否包含指定的值
    boolean isEmpty() 判断集合是否为空
    int size() 集合的长度,也就是集合中键值对的个数
  • 示例代码

    package com.itheima.mapdemo1;

    import java.util.HashMap;
    import java.util.Map;
    /**
    * Map的基本方法
    */
    public class MyMap2 {
       public static void main(String[] args) {
         Map<String,String> map = new HashMap<>();
           map.put("itheima001","小智");
           map.put("itheima002","小美");
           map.put("itheima003","大胖");
         map.put("itheima004","小黑");
           map.put("itheima005","大师");

         //method1(map);
           //method2(map);
           //method3(map);
           //method4(map);
         //method5(map);
           //method6(map);
           //method7(map);

      }

     private static void method7(Map<String, String> map) {
           //       int size()             集合的长度,也就是集合中键值对的个数
           int size = map.size();
           System.out.println(size);
      }

       private static void method6(Map<String, String> map) {
           //       boolean isEmpty()       判断集合是否为空
           boolean empty1 = map.isEmpty();
           System.out.println(empty1);//false

           map.clear();
           boolean empty2 = map.isEmpty();
           System.out.println(empty2);//true
      }

       private static void method5(Map<String, String> map) {
           //       boolean containsValue(Object value) 判断集合是否包含指定的值
           boolean result1 = map.containsValue("aaa");
           boolean result2 = map.containsValue("小智");
           System.out.println(result1);
           System.out.println(result2);
      }

       private static void method4(Map<String, String> map) {
           //       boolean containsKey(Object key) 判断集合是否包含指定的键
           boolean result1 = map.containsKey("itheima001");
           boolean result2 = map.containsKey("itheima006");
           System.out.println(result1);
           System.out.println(result2);
      }

       private static void method3(Map<String, String> map) {
           //       void clear()           移除所有的键值对元素
           map.clear();
           System.out.println(map);
      }

       private static void method2(Map<String, String> map) {
           //       V remove(Object key)   根据键删除键值对元素
           String s = map.remove("itheima001");
           System.out.println(s);
           System.out.println(map);
      }

       private static void method1(Map<String, String> map) {
           //       V put(K key,V value)   添加元素
           //如果要添加的键不存在,那么会把键值对都添加到集合中
           //如果要添加的键是存在的,那么会覆盖原先的值,把原先值当做返回值进行返回。
           String s = map.put("itheima001", "aaa");
           System.out.println(s);
           System.out.println(map);
      }
    }

3.3Map-第一种遍历方式【重点】

方法介绍

方法名说明
Set<K> keySet() 获取所有键的集合
V get(Object key) 根据键获取值

 

 

示例代码

package com.itheima.mapdemo1;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Map的第一种遍历方式
*/
public class MyMap3 {
 public static void main(String[] args) {
       //创建集合并添加元素
       Map<String,String> map = new HashMap<>();
       map.put("1号丈夫","1号妻子");
     map.put("2号丈夫","2号妻子");
       map.put("3号丈夫","3号妻子");
       map.put("4号丈夫","4号妻子");
       map.put("5号丈夫","5号妻子");

       //获取到所有的键
     Set<String> keys = map.keySet();
       //遍历Set集合得到每一个键
       for (String key : keys) {
           //通过每一个键key,来获取到对应的值
           String value = map.get(key);
           System.out.println(key + "---" + value);
      }
  }
}

3.4Map-第二种遍历方式【重点】

方法介绍

方法名说明
Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象集合
K getKey() 获得键值
V getValue() 获得值

 

 

 

 

示例代码

package com.itheima.mapdemo1;

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

/**
* Map的第二种遍历方式
*/
public class MyMap4 {
   public static void main(String[] args) {
       //创建集合并添加元素
       Map<String,String> map = new HashMap<>();
       map.put("1号丈夫","1号妻子");
       map.put("2号丈夫","2号妻子");
       map.put("3号丈夫","3号妻子");
       map.put("4号丈夫","4号妻子");
       map.put("5号丈夫","5号妻子");

       //首先要获取到所有的键值对对象。
       //Set集合中装的是键值对对象(Entry对象)
       //而Entry里面装的是键和值
       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);
      }
  }
}

4.HashMap集合

4.1HashMap-原理解析【难点】

1.HashMap小结

  • HashMap底层是哈希表结构

  • 依赖hashCode方法和equals方法保证键的唯一

  • 如果键要存储自定义对象,需要重写hashCode和equals方法

 

 

 

 

4.2 HashMap集合-练习【重点】

(共4点,第4点是对forEache的解析)

1.案例需求

  • 创建一个HashMap集合,键是学生对象(Student),值是籍贯 (String)。存储三个元素,并遍历。

  • 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象

2.实现思路

  • 定义学生类

  • 创建HashMap集合对象

  • 添加学生对象

  • 为了保证key的一致性,重写学生类的hashCode和equals方法

3.代码实现

学生类

package com.itheima.mapdemo1;

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;

       if (age != student.age) return false;
       return name != null ? name.equals(student.name) : student.name == null;
  }

   @Override
   public int hashCode() {
       int result = name != null ? name.hashCode() : 0;
       result = 31 * result + age;
       return result;
  }

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

测试类

package com.itheima.mapdemo1;

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

/**
* Map的练习
*/
public class MyMap5 {
   public static void main(String[] args) {
       HashMap<Student,String> hm = new HashMap<>();

       Student s1 = new Student("xiaohei",23);
       Student s2 = new Student("dapang",22);
       Student s3 = new Student("xiaomei",22);

       hm.put(s1,"江苏");
       hm.put(s2,"北京");
       hm.put(s3,"天津");

       //第一种:先获取到所有的键,再通过每一个键来找对应的值
       Set<Student> keys = hm.keySet();
       for (Student key : keys) {
           String value = hm.get(key);
           System.out.println(key + "----" + value);
      }

       System.out.println("===================================");

       //第二种:先获取到所有的键值对对象。再获取到里面的每一个键和每一个值
       Set<Map.Entry<Student, String>> entries = hm.entrySet();
       for (Map.Entry<Student, String> entry : entries) {
           Student key = entry.getKey();
           String value = entry.getValue();
           System.out.println(key + "----" + value);
      }
       System.out.println("===================================");
       //第三种:
       hm.forEach(
              (Student key, String value)->{
                   System.out.println(key + "----" + value);
              }
      );

  }
}

4.forEach方法解析

 

 

5.TreeMap集合

5.1TreeMap-原理解析【了解】

1.TreeMap-小结

  • TreeMap底层是红黑树结构

  • 依赖自然排序或者比较器排序,对键进行排序

  • 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则

5.2TreeMap集合应用案例【重点】

  • 案例需求

    • 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历

    • 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序

  • 实现思路

    1.创建学生类

    2.创建TreeMap集合对象

    3.创建学生对象

    4.添加学生对象

    5.遍历输出

  • 代码实现

    学生类

    package com.itheima.maptest;

    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 int compareTo(Student o) {
           //按照年龄进行排序
           int result = o.getAge() - this.getAge();
           //次要条件,按照姓名排序。
           result = result == 0 ? o.getName().compareTo(this.getName()) : result;
           return result;
       }*/
    }

    测试类

    package com.itheima.maptest;
    
    import java.util.Comparator;
    import java.util.TreeMap;
    
    /**
     * 需求:创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String)。
     *           学生属性姓名和年龄,按照年龄进行排序并遍历。
     */
    public class Test1 {
        public static void main(String[] args) {
            TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    int result = o1.getAge() - o2.getAge();
                    result = result== 0 ? o1.getName().compareTo(o2.getName()) : result;
                    return result;
                }
            });
    
            Student s1 = new Student("xiaohei",23);
            Student s2 = new Student("dapang",22);
            Student s3 = new Student("xiaomei",22);
    
            tm.put(s1,"江苏");
            tm.put(s2,"北京");
            tm.put(s3,"天津");
    
            tm.forEach(
                    (Student key, String value)->{
                        System.out.println(key + "---" + value);
                    }
            );
        }
    }

                  ==扩展练习==

题目1

假如你有3个室友,请使用HashSet集合保存3个室友的信息;

信息如下:

赵丽颖,18

范冰冰,20

杨幂,19

要求:

1:室友以对象形式存在,包含姓名和年龄两个属性;

2:使用代码保证集合中同名同年龄的对象只有一份;(相同姓名和年龄的对象认为是同一个对象)

效果:

 

 

参考答案:

测试类:
class Demo {
   public static void main(String[] args) {
       Student s1=new Student("赵丽颖",18);
       Student s2=new Student("范冰冰",18);
       Student s3=new Student("杨幂",19);
       HashSet<Student> hs=new HashSet<>() ;
       hs.add(s1);
       hs.add(s2);
       hs.add(s3);
       System.out.println(hs);
  }
}
类文件:
package day9.No_1;

public class Student {
   private String name;
   private int age;

   public Student() {
  }

   public Student(String name, int age) {
       this.name = name;
       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;

       if (age != student.age) return false;
       return name != null ? name.equals(student.name) : student.name == null;
  }

   @Override
   public int hashCode() {
       int result = name != null ? name.hashCode() : 0;
       result = 31 * result + age;
       return result;
  }

   @Override
   public String toString() {
       return "Student{" +
               "name=\'" + name + \'\\'\' +
               ", 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;
  }
}

题目2

请使用HashMap集合保存街道两旁的店铺名称;使用门牌号作为键,店铺名作为值,然后使用三种方式遍历输出;

信息如下:

101,阿三面馆

102,阿四粥馆

103,阿五米馆

104,阿六快递

要求:

1:键是整数,值是字符串;

2:输出的信息使用"--"链接

效果:

 

 

参考答案:

package day9.No_2;

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

public class Demo {
   public static void main(String[] args) {
       HashMap<Integer,String>hs=new HashMap<>() ;
       hs.put(101,"阿三面馆");
       hs.put(102,"阿四粥馆");
       hs.put(103,"阿五米馆");
       hs.put(104,"阿六快递");
       System.out.println("方式一遍历\t键值查找");
       System.out.println("=================");
       Set<Integer> keys = hs.keySet();
       for (Integer key : keys) {
           String value = hs.get(key);
           System.out.println(key+"--"+value);
      }
       System.out.println("方式二遍历\t键值对对象");
       System.out.println("=================");
       Set<Map.Entry<Integer, String>> entries = hs.entrySet();
       for (Map.Entry<Integer, String> entry : entries) {
           Integer key = entry.getKey();
           String value = entry.getValue();
           System.out.println(key+"--"+value);
      }
       System.out.println("方式三遍历\t使用接口");
       System.out.println("=================");
       hs.forEach(( i, s)->
           System.out.println(i+"--"+s)
      );//lambda简写格式
  }
}

 

题目3(综合题,有难度)

请使用TreeMap集合保存劳模信息,要求以劳模对象为键,家庭住址为值,并按照劳模的年龄从大到小排序后输出;

 

信息如下:

18岁的张三,北京

20岁的李四,上海

35岁的王五,天津

21岁的赵六,北京

19岁的田七,上海

要求:

1:劳模类中有姓名和年龄两个属性;

2:添加上述信息后,使用代码删除张三的信息

3:添加上述信息后,使用代码修改李四的家庭住址为郑州

4:使用至少两种方式遍历集合中的信息并输出;

效果:

 

 

参考答案:

TreeMap根据key中的指定元素进行删除修改的及注意事项:

 

 

利用迭代器进行修改和删除,但是增强for只能进行修改,用来删除将会报错,则该方法不能进行删除,删除将报错,凑巧要删除的是最后一个才能删除,所以此方式不可用来删除,但是可以修改使用

如果用来删除那么将会该异常如果用来修改将会出现以下错误信息:

使用迭代器,都能进行修改和删除

修改不会改变值得个数,所以修改可以使用迭代器,也可以直接使用增强for进行修改

@Override
   public int compareTo(Student o) {
       int i = this.age - o.age;
       Collator instance = Collator.getInstance(Locale.CHINESE);//因为值可能为汉字所以使用Collator静态方法,对汉字进行比较方法
       i=i==0?instance.compare(this.name,o.name):i;
       return i;
       //return -i;//因为要从大到小,而默认规则是负数存左边,正数存右边,排序规则根据返回值而定的,所以直接加减负可以直接改变大小原则
  }

 

 class Demo1 {
   public static void main(String[] args) {
       Student s1 = new Student("张三", 23);
       Student s2 = new Student("李四", 24);
       Student s3 = new Student("王五", 25);
       Student s4 = new Student("赵六", 26);
       TreeMap<Student, String> ts = new TreeMap<>();
       ts.put(s1, "北京");
       ts.put(s2, "上海");
       ts.put(s3, "广东");
       ts.put(s4, "深圳");
       Set<Student> keySet = ts.keySet();
//迭代器删除方式,删除key的姓名为李四的键值对
       Iterator<Student> iterator1 = keySet.iterator();
       while (iterator1.hasNext()) {
           Student key = iterator1.next();
           if (key.getName().equals("李四")) {
               iterator1.remove();//此时注意是用的迭代器的删除方法,而不是Map集合的删除方法,使用Map集合删除方法,此处会报错
          }
      }
       //修改方式一:
       //迭代器修改方式,将张三的值修改为郑州
       Iterator<Student> iterator = keySet.iterator();
       while (iterator.hasNext()) {
           Student key = iterator.next();
           if (key.getName().equals("张三")) {
               ts.put(key, "郑州");
               System.out.println("修改成功");
               
          }
      }
       //bug代码:
       /*
       Iterator<Student> iterator = keySet.iterator();
       while (iterator.hasNext()) {
           if (iterator.next().getName().equals("张三")) {
               ts.put(iterator.next(), "郑州");
           }//此逻辑不会编译报错,运行也不报错,但是逻辑不通,,但是会修改到下一个key的值,迭代器的默认指向下一个原理
       }*/
       
        /*
        //修改方式二,增强for修改
        for (Student key : keySet) {
           if (key.getName().equals("张三")){
               ts.put(key,"郑州");
               System.out.println("修改成功");
           }
       }
       */
       System.out.println(ts);
       System.out.println("遍历:");
       for (Student key : keySet) {
           String value = ts.get(key);
           System.out.println(key.getAge() + "岁的" + key.getName() + "," + value);
      }

  }
}

效果如下:

从大到小排序:

从小到大排序: