TreeSet
无参构造方法
特点:该set集合根据其元素的自然顺序进行排序;插入该 set 的所有元素都必须实现 Comparable
接口。另外所有这些元素都必须是相互可比较的。
分析:通过源码我们可以知道内部创建Comparable比较器对象,调用了元素键对象类型的compareTo方法
实现Comparable接口的常用类:Integer、String等
实例1
package org.westos_04;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args){
/*
throw new IOException();-----不是太懂?
public TreeSet():无参构造:根据其元素的自然顺序进行排序
publict TreeSet(Comparaptr<E> com)
*
*/
TreeSet<Integer> ts = new TreeSet<Integer>();//
ts.add(20);//装箱: Integer i = Integer.valueOf(20);
ts.add(18) ;
ts.add(23) ;
ts.add(22) ;
ts.add(17) ;
ts.add(24) ;
ts.add(19) ;
ts.add(18) ;
ts.add(24) ;
//增强for遍历元素
for(Integer i : ts){
System.out.print(i+ " ");//17 18 19 20 22 23 24 :唯一并且排序:自然排序(升序排序)
}
}
}
问题来了,如果自定义的类呢?显然也得实现Comparable接口。
由于Comparable接口只有一个非静态的方法,方法描述如下:
int compareTo(T o)------返回值表示两个对象的大小关系
因此必须实现compareTo的方法!!!
实例2
Student类
package org.westos_04;
//对于TreeSet集合存储自定义对象必须实现一个接口:Compareable接口
public class Student implements Comparable<Student>{
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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;
}
//重写了compareTo()方法
@Override
public int compareTo(Student s) {
//排序的代码了,需要定义排序的条件
//主要条件:按照学生的年龄从小到大进行排序
int num =s.age - this.age ;//年龄从大到小
//当num==0认为年龄一样,年龄一样,不代表姓名的的内容是否相同,需要自己给出次要条件
int num2 = num==0 ? this.name.compareTo(s.name): num ;
return num2 ;
}
}
测试类
package org.westos_04;
import java.util.TreeSet;
/**
* TreeSet集合存储自定义对象并遍历
* 实现了compareable接口,重写了comapreTo()方法,里面的逻辑是一个排序条件:
* 需求:
* 按照学生的年龄从小到大进行排序:主要条件
* 对于自定义对象什么情况下保证元素是唯一的
* 成员变量的值相同,认为是同一个元素
* 主要条件给定,需要分析次要条件
*
* 一个类中的元素想要自然排序,那么必须实现Compareable接口,实现compareTo(类名 对象名){}方法
*
* 按照正常存储对象的操作以及遍历对象出现了问题:
* 类转换异常
* java.lang.ClassCastException: org.westos_04.Student cannot be cast to java.lang.Comparable
*
* @author Apple
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
//创建TreeSet集合对象
TreeSet<Student> ts = new TreeSet<Student>() ;//
//创建学生对象
Student s1 = new Student("linqingxia", 28) ;
Student s2 = new Student("fengqingy", 28) ;
Student s3 = new Student("gaoyuanyuan", 27) ;
Student s4 = new Student("liushishi", 26) ;
Student s5 = new Student("wanglihong", 29) ;
Student s6 = new Student("zhangguorong", 30) ;
Student s7 = new Student("zhangguorong", 30) ;
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
//遍历
for(Student s : ts){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
问题:如果自定义的类不实现该接口,出现
类转换异常
补充:关于compareTo的业务逻辑实现需要根据需求自己码!!!
常见分析流程:主要条件和次要条件
有参的构造方法
public TreeSet(Comparator<? super E> comparator)
比较器:在外部创建比较器----需要我们创建一个实现该接口的比较器对象
Comparator接口中的方法:int compare(T o1, T o2) 和equals()方法
方式1:内部类的形式(节省代码量)
实例3 Student类
package org.westos_06;
public class Student {
private String name ;
private int age ;
public Student() {
super();
}
public Student(String name, int age) {
super();
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;
}
}
测试类
package org.westos_06;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 需求:按照学生姓名长度从小到大进行排序
*
* //元素唯一性:取决返回值是否为0
* 要使用TreeSet集合的比较器排序:
* 依赖于构造方法:
* public TreeSet(Comparator<E> comparator)
*
* 两种方式实现比较器排序:
* Comparator接口作为形式参数进行传递,需要该接口的子实现类对象
* @author Apple
*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建TreeSet集合使用比较器进行给元素进行排序
//public TreeSet(Comparator<E> comparator):有参构造
//方式1:自定义一个类,类实现Comparator接口,作为子实现类
//方式2:可以使用接口的匿名内部类来实现:开发中,由于减少代码书写量,不需要自定义接口的子实现类,直接这种格式!
/**
* 格式
* new 接口名或者类名(){
* 重写方法() ;
* }
*/
// TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// return 0;//返回值主要说明对象比较结果
int num = s1.getName().length() - s2.getName().length() ;
//次要条件:姓名长度一样,还要比较姓名的内容是否一样
int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;
//姓名长度和内容都一样,还需比较两个人的年龄是否一样
int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
return num3 ;
}
}) ;
//创建学生对象
Student s1 = new Student("gaoyuanyan", 27) ;
Student s2 = new Student("liushishi", 22);
Student s3 = new Student("fengqingy", 23) ;
Student s4 = new Student("wuqilong", 35) ;
Student s5 = new Student("gaoyuanyuan",27) ;
Student s6 = new Student("zhangguorong",29) ;
Student s7 = new Student("gaoyuanyuan",26) ;
//添加元素
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
//增强for遍历
for(Student s : ts){
System.out.println(s.getName()+"----"+s.getAge());
}
}
}
方式2:定义一个实现该接口子类,实现对象的比较
实例4 Student同上
自定义类:实现Comparator接口
package org.westos_06;
import java.util.Comparator;
//MyComparatpr是Comparator接口的子实现类
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// return 0;
// 按照学生姓名长度从小到大进行排序
//int num = this.name.lengt()-s.name.length();
//this--:s1
//s---:s2
int num = s1.getName().length() - s2.getName().length() ;
//次要条件:姓名长度一样,还要比较姓名的内容是否一样
int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;
//compareTo可以用的原因---s1.getName()是String--该类实现了Comparable的接口的方法
//姓名长度和内容都一样,还需比较两个人的年龄是否一样
int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
return num3 ;
}
}