Java集合之TreeSet的排序规则(部分源码)

前言

上一篇说了红黑树的实现——平衡二叉树和红黑树-CSDN博客

这一次说的是集合TreeSet的排序原理,跟红黑树有很大的联系。

目录

前言

一、前菜

1.先看结论

2.TreeSet排序的底层源码

 (1)先插入一个数据作为根

(2)添加后面的数据 

二、数值类型和Char、String的比较器

1.数值类型

2.字符和字符串

三、自定义类实现comparable和comparator

1.自定义类实现Comparable接口

2.匿名内部类方式实现comparator接口

3.新建比较器类实现comparator接口


一、前菜

前面就有说TreeSet底层是TreeMap,TreeMap的底层是红黑树。

红黑树就是二叉查找树+维护红黑规则,也就是小的放左边,大的放右边,+红黑规则维护。

这次要说的是TreeSet的底层是怎么实现小的放左边,大的放右边。以及java包装好的基本类型包装类和String的排序规则   +   自定义类的排序规则如何设计。

1.先看结论

TreeSet底层是通过类实现的比较器来实现的,比如compareTo()方法。

2.TreeSet排序的底层源码

 (1)先插入一个数据作为根

下面进入到TreeMap的put()方法,进入到compare()方法是不返回任何数值的,第一个数据只要不是null就作为红黑树的根

(2)添加后面的数据 

下面这部分代码是put()方法接下来的部分,处理非根的数据,数据会进入compare()方法,第一层循环先将根作为父节点,跟父节点比较,如果比父节点小,就进入到父节点的左边,如果比父节点大就放右边,相等就丢掉。

如果进入的位置不为空,就将当前位置的节点作为父节点,继续上面的流程。直到遇到空的位置。

最后一次循环compare()返回的int数值cmp小于0,将数据放到父节点左边,反之,放到右边。


 

二、数值类型和Char、String的比较器

数值类型和Char、String的比较器是java包装好的,这些类实现camparable接口,并重写compareTo(添加的数据)方法

1.数值类型

以Integer,Double为例,默认按照从小到大的顺序进行排序。

x是正在添加的数据       y是正在比较的父节点

 

上面是Integer包装类的比较器方法,在TreeSet底层,添加一个数据时,将父节点传入到要添加的数据对象的compare()方法作为参数进行比较。如果大于父节点返回1,如果小于父节点返回-1,相等的话返回0。

2.字符和字符串

照字符在ASCII码表中的数字升序进行排序。如果是字符串的话,先比较字符串的第一个字符,如果第一个字符一样,就比较第二个字符,直到最短字符串结束。如果字符都相等,返回正在添加的字符串的长度减父节点字符串的长度。

下面是String类封装好的compareTo()方法。


 

三、自定义类实现comparable和comparator

自定义类要放在TreeSet中就要实现comparable或者comparator,不然代码运行会报错的。

下面介绍三种实现方法

1.自定义类实现Comparable接口

示例代码:

import java.util.TreeSet;  
 
// 自定义类 Person 实现 Comparable 接口  
class Person implements Comparable<Person> {  
    private String name;  
    private int age;  
 
    // 构造函数  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
 
    // Getter 方法  
    public String getName() {  
        return name;  
    }  
 
    public int getAge() {  
        return age;  
    }  
 
    // 重写 compareTo 方法  
    @Override  
    public int compareTo(Person other) {  
        // 按年龄升序排列  
        return Integer.compare(this.age, other.age);  
        // 如果需要按名字排序,可以使用以下代码:  
        // return this.name.compareTo(other.name);  
    }  
 
    @Override  
    public String toString() {  
        return "Person{name='" + name + "', age=" + age + "}";  
    }  
}  
 
public class TreeSetExample {  
    public static void main(String[] args) {  
        // 创建 TreeSet 实例  
        TreeSet<Person> treeSet = new TreeSet<>();  
 
        // 添加 Person 对象  
        treeSet.add(new Person("Alice", 30));  
        treeSet.add(new Person("Bob", 25));  
        treeSet.add(new Person("Charlie", 35));  
 
        // 输出 TreeSet 中的 Person 对象  
        for (Person person : treeSet) {  
            System.out.println(person);  
        }  
    }  
}

运行结果:

2.匿名内部类方式实现comparator接口

示例代码:

// 自定义类 Person  
class Person {  
    private String name;  
    private int age;  
 
    // 构造函数  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
 
    // Getter 方法  
    public String getName() {  
        return name;  
    }  
 
    public int getAge() {  
        return age;  
    }  
 
    @Override  
    public String toString() {  
        return "Person{name='" + name + "', age=" + age + "}";  
    }  
}  
 
public class ComparatorExample {  
    public static void main(String[] args) {  
        // 使用匿名内部类按年龄排序的 TreeSet  
        TreeSet<Person> ageSortedSet = new TreeSet<>(new Comparator<Person>() {  
            @Override  
            public int compare(Person p1, Person p2) {  
                return Integer.compare(p1.getAge(), p2.getAge());  
            }  
        });  
        
        ageSortedSet.add(new Person("Alice", 30));  
        ageSortedSet.add(new Person("Bob", 25));  
        ageSortedSet.add(new Person("Charlie", 35));  
 
        System.out.println("按年龄排序:");  
        for (Person person : ageSortedSet) {  
            System.out.println(person);  
        }  
 
        // 使用匿名内部类按名字排序的 TreeSet  
        TreeSet<Person> nameSortedSet = new TreeSet<>(new Comparator<Person>() {  
            @Override  
            public int compare(Person p1, Person p2) {  
                return p1.getName().compareTo(p2.getName());  
            }  
        });  
        
        nameSortedSet.add(new Person("Alice", 30));  
        nameSortedSet.add(new Person("Bob", 25));  
        nameSortedSet.add(new Person("Charlie", 35));  
 
        System.out.println("\n按名字排序:");  
        for (Person person : nameSortedSet) {  
            System.out.println(person);  
        }  
    }  
}

运行结果: 

3.新建比较器类实现comparator接口

示例代码:

// 自定义类 Person  
class Person {  
    private String name;  
    private int age;  
 
    // 构造函数  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
 
    // Getter 方法  
    public String getName() {  
        return name;  
    }  
 
    public int getAge() {  
        return age;  
    }  
 
    @Override  
    public String toString() {  
        return "Person{name='" + name + "', age=" + age + "}";  
    }  
}  
 
// 按年龄排序的比较器  
class AgeComparator implements Comparator<Person> {  
    @Override  
    public int compare(Person p1, Person p2) {  
        return Integer.compare(p1.getAge(), p2.getAge());  
    }  
}  
 
// 按名字排序的比较器  
class NameComparator implements Comparator<Person> {  
    @Override  
    public int compare(Person p1, Person p2) {  
        return p1.getName().compareTo(p2.getName());  
    }  
}  
 
public class ComparatorExample {  
    public static void main(String[] args) {  
        // 根据年龄排序的 TreeSet  
        TreeSet<Person> ageSortedSet = new TreeSet<>(new AgeComparator());  
        ageSortedSet.add(new Person("Alice", 30));  
        ageSortedSet.add(new Person("Bob", 25));  
        ageSortedSet.add(new Person("Charlie", 35));  
 
        System.out.println("按年龄排序:");  
        for (Person person : ageSortedSet) {  
            System.out.println(person);  
        }  
 
        // 根据名字排序的 TreeSet  
        TreeSet<Person> nameSortedSet = new TreeSet<>(new NameComparator());  
        nameSortedSet.add(new Person("Alice", 30));  
        nameSortedSet.add(new Person("Bob", 25));  
        nameSortedSet.add(new Person("Charlie", 35));  
 
        System.out.println("\n按名字排序:");  
        for (Person person : nameSortedSet) {  
            System.out.println(person);  
        }  
    }  
}

 运行结果:

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值