TreeSet集合的使用

TreeSet集合

目录

TreeSet集合

自然排序:Comparable接口的使用

案例分析

总结

比较器排序Comparator的使用

两种方法比较


public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable
  • 元素有序,但这里的顺序不是元素的存储与取出顺序,而是按照一定规则进行的排序,具体排序方式取决于构造方法 :TreeSet() : 无参构造,根据其元素的自然排序进行排序

    TreeSet(Comparator comparator) : 根据指定的比较器进行排序

  • 没有带索引的方法,所以不能使用普通for循环

  • 是Set集合,所以不包含重复元素

import java.util.TreeSet;
​
public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();        //<>中不能为基本数据类型
​
        ts.add(10);
        ts.add(40);
        ts.add(60);
        ts.add(20);
​
        ts.add(20);
​
        for(Integer i : ts){
            System.out.println(i);
        }
    }
}
​
​
//  自然排序
10
20
40
60
​

自然排序:Comparable接口的使用

  • 该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法

只有唯一方法:

int compareTo(T o)
将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。 

案例分析

问题

//学生类,没有实现Comparable接口
public class Student {
    private String name;
    private int age;
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    public Student() {
    }
​
    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;
    }
​
}
//demo,运行会报错
//未覆盖java.lang.Comparable中的抽象方法compareTo(com.Set.TreeSetD.Student)
​
import java.util.TreeSet;
public class demo {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>();
​
        Student s1 = new Student("林青霞",33);
        Student s2 = new Student("张曼玉",23);
        Student s3 = new Student("眼红和",14);
        Student s4 = new Student("金城武",32);
​
​
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
​
        for(Student s : ts){
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}

解决方法

  • 让学生类实现Comparable接口

  • 让学生类重写CompareTo方法

public class Student implements Comparable<Student>{
  ...
  @Override
    public int compareTo(Student s) {
        return 0;
    }
}

执行dome类结果是:

林青霞,33 //只有一个元素,原因是在重写后默认比较规则中,返回值是0,是0则认为添加来的元素跟比较的是一样的

返回值改为恒正数

再次重写

public class Student implements Comparable<Student>{
  ...
  @Override
    public int compareTo(Student s) {
        return 1;
    }
}

执行dome类结果是:

林青霞,33
张曼玉,23
眼红和,14
金城武,32   //跟存入顺序相同

返回值改为恒负数

再次重写

public class Student implements Comparable<Student>{
  ...
  @Override
    public int compareTo(Student s) {
        return -1;
    }
}

执行dome类结果是:

金城武,32
眼红和,14
张曼玉,23
林青霞,33   //跟存入顺序相反

按需求改写为 按年龄排序

再次重写

public class Student implements Comparable<Student>{
  ...
  @Override
    public int compareTo(Student s) {
        return this.getAge()-s.getAge();
    }
}

执行dome类结果是:

眼红和,14
张曼玉,23
金城武,32
林青霞,33  //跟年龄大小顺序保持一致

bug

import java.util.TreeSet;
public class demo {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>();
​
        Student s1 = new Student("林青霞",33);
        Student s2 = new Student("张曼玉",23);
        Student s3 = new Student("眼红和",14);
        Student s4 = new Student("金城武",32);
​
        Student s5 = new Student("胡一菲",32);
​
​
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
​
        for(Student s : ts){
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}
​
//
        Student s4 = new Student("金城武",32);
​
        Student s5 = new Student("胡一菲",32);
        
       年龄相同则认为他们俩为同一个对象,就不存入此集合

解决办法:

@Override
public int compareTo(Student s) {
    int num = this.age-s.age;
    int num2 = num == 0 ? this.name.compareTo(s.name):num; 
    //String类可以直接使用该方法,因为String类实现了Comparable接口并且重写了该方法
    return num2;
}

执行dome类结果是:

眼红和,14
张曼玉,23
胡一菲,32
金城武,32
林青霞,33

总结

  • 用TreeSet集合存储自定义对象,无参构造方法使用自然排序会报错

  • 自然排序,就是让所属的类实现Comparable接口,重写CompareTo()方法

  • 重写方法时,一定要注意排序规则必须按照要求的主要次要条件进行

比较器排序Comparator的使用

public static void main(String[] args) {
    TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {  //匿名内部类
        @Override
        public int compare(Student o1, Student o2) {      //在Comparator中重写compare方法
            int num = o1.getAge()- o2.getAge();
            int num2 = num == 0 ? o1.getName().compareTo(o2.getName()):num;    
            return num2;
        }
    });
​
​
    Student s1 = new Student("林青霞",33);
    Student s2 = new Student("张曼玉",23);
    Student s3 = new Student("眼红和",14);
    Student s4 = new Student("金城武",32);
​
    Student s5 = new Student("胡一菲",32);
​
​
    ts.add(s1);
    ts.add(s2);
    ts.add(s3);
    ts.add(s4);
    ts.add(s5);
​
    for(Student s : ts){
        System.out.println(s.getName()+","+s.getAge());
    }
}
​
//
眼红和,14
张曼玉,23
胡一菲,32
金城武,32
林青霞,33

两种方法比较

自然排序比较器排序
使用的接口或者类Comparable接口Comparator类(可实例化)
使用方法在TreeSet的无参构造中使用在TreeSet的有参构造中使用(匿名内部类)
重写的内容以及位置在Student(元素类型类)中实现Comparable接口并重写CompareTo方法直接在构造器的匿名内部类中重写Compare方法

使用TreeSet集合最需要注意的就是:
- 次要条件的分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值