JAVA集合之——TreeSet
来源:互联网 发布:淘宝链接怎么做的 编辑:程序博客网 时间:2024/05/21 10:41
JAVA集合之——TreeSet
一、TreeSet的排序原理
TreeSet是有序的,且不可以重复的集合,首先,进行如下测试:
public static void main(String[] args){//1. 创建一个存储Integer类型的TreeSetTreeSet<Integer> set = new TreeSet<Integer>();//无序添加对像set.add(40);set.add(10);set.add(10);set.add(30);set.add(20);//打印//从结果来看数据是有序输出的,并且重复的对像不会被添加//TreeSet是一个Sorted Collectionfor(int x: set){System.out.println(x);}//2. 创建一个存储String类型的TreeSetTreeSet<String> set1 = new TreeSet<>();//无序添加对像set1.add("Hello");set1.add("World");set1.add("World");set1.add("JAVA SE");set1.add("JAVA EE");//打印//打印结果是按字符串排序的,并且得复的元素不会被添加for(String s: set1){System.out.println(s);}}经过测试发现,TreeSet对插入的元素进行了排序,并且不可插入重复的元素,那TreeSet是怎样做到的呢?
对一个自定义的对像Persion进行如添加元素,打印操作,如下:
public static void main(String[] args){//创建一个TreeSetTreeSet<Persion> set = new TreeSet<>();//添加自定义元素set.add(new Persion("张三", 50));set.add(new Persion("李四", 30));set.add(new Persion("麻子", 20));set.add(new Persion("麻子", 40));//打印测试for(Persion p: set){System.out.println(p.getName() + p.getAge());}}然而,当运行的时候,出错了,错误信息如下:
TreeSet.Persion cannot be cast to java.lang.Comparable
原来,在默认的情况下,TreeSet假定插入的元素产现了Comparable接口,关于Comparable接口,JDK文档抄录如下:
接口 Comparable<T>
类型参数:T - 可以与此对象进行比较的那些对象的类型
接口原型:
public interface Comparable<T>{int compareTo(T other);}此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo 方法被称为它的自然比较方法。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。 实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。对于上面的Iteger类型按大小排序,对于String类,它的commpareTo方法依据字典序对字符串进行比较。这些类是JAVA标准类库,已经实现了Comparable接口。
如果要插入自定义对像,就必须实现Comparable接口自定义排序规则,即实现compareTo方法,这个方法的算法如何实现,就看自已的需求了,如果按照年年龄进行排序,那么Persion类的定义如下:
public class Persion implements Comparable<Persion>{private String name;private int age;public Persion(String name,int age){this.name = name;this.age = age;}public String getName(){return this.name;}public int getAge(){return this.age;}//自定义类,要实现Comparable接口的compareTo方法public int compareTo(Persion other){return this.age - other.age;}}如上代码所示,compareTo方法的实现是依照Persion对像的年龄比较,所以重新运行主程序代码,添加元素后,打印输出是按年龄排序的。
实际上,在使用TreeSet存储对像时,它的add()方法是会自动的调用compareTo方法来进行对像的比较,如果相同的元素,就不存储,不相同则按照红黑树(一种自平衡的二叉树)的算法进行存储。
即,如果a和b相等,调用a.compareTo(b)一定返回0;如果排序后a位于b之前,则返回负值;如果a位于b之后,则返回正值。
对于上面的例子,如果添加一行:
set.add(new Persion("小明", 50));
经测试发现这个元素是没有被添加进去的。为什么?
上面的compareTo方法是按age进行比较的,age相同,则被认为是相同的对像,所以没有添加进去,所以对于compareTo方法的实现方式,是要根据需求来定的,经过更改,我们采用下面的方式,看起来更完善一些。
public int compareTo(Persion other){//首先按age排序int num = this.age - other.age;//如果age相同按name排序if(num == 0){return this.name.compareTo(other.name);}//执行到此表示age不同,返回比较结果return num;}经测试,name和age都相同的元素添加不进去,有一个不同的元素可以添加,验证了我们的想法。
二、Comparable与Comparator的区别。
使现Comparable接口的compareTo方法有一定的局限性。对于一个给定的类,只能够实现这个接口一次。对于上面的Persion类,在一个集合中需要按age进行排序, 在另一个集中需要按name进行排序,那要怎么办? 另外,如果Persion类的实现者没有实现Comparable接口中,又该怎么办呢?
这时,Comparator就表现出了极大的灵活性了,TreeSet有一个构造方法:
TreeSet(Comparator<? super E> comparator)
--------- 构造一个新的空 TreeSet,它根据指定比较器进行排序。
如上面所示,在创建集合时,将自已实现的Comparator对像传递给TreeSet构造器,Comparator也是一个接口,它的完整描述如下:
public interface Comparator<T>{int compare(T a,T b);}与compareTo方法一样,如果a位于b之前,compare方法返回负值;如果a和b相等,则返回0;否则返回正值。查JDK文档发现,该接口还有一个equals方法,但是不需要实现。
通常,使用匿名内部类的方式将实现的Comparator对像传递给TreeSet构造器:
TreeSet<Persion> set = new TreeSet<>(new Comparator<Persion>() { public int compare(Persion a, Persion b) { //首先按age排序 int num = a.getAge() - b.getAge(); //如果age相同按name排序 if(num == 0) { return a.getName().compareTo(b.getName()); } //执行到此表示age不同,返回比较结果 return num; } });这样的话,对于基本的Persion是固定的,而在不同的集合中却可以使用不同的排序规则对集合元素进行排序,灵活性大大提高。
总结,TreeSet集合保证元素有序和唯一的原理:
1. 唯一性: 调用add()时通过比较返回是否为0来确确定元素是否相同。
2. 有序:
A: 自然排序(元素具备比较性) —— 元素所属的类实现自然排序的Comparable接口。
B: 比较器排序(集合具备比较性) —— 集合的构造方法接收一个比较器Comparator的子类对像。
关于HashSet和TreeSet的选择:
如果不需要对元素进行排序,就没必要付出使用TreeSet所带来的排序开销。
- JAVA集合之——TreeSet
- Java集合之TreeSet
- java集合之TreeSet
- Java集合之TreeSet
- Java集合之TreeSet
- Java集合之TreeSet
- Java集合之TreeSet
- 黑马程序员:Java基础——Set集合之TreeSet
- java基础之—TreeSet集合学习笔记
- Java Set集合之Treeset
- java集合系列——Set之HashSet和TreeSet介绍(十)
- java学习笔记:集合框架之TreeSet
- java学习笔记:集合框架之TreeSet
- Java---28---Set集合之TreeSet
- java基础集合之TreeSet(上)
- java基础集合之TreeSet(下)
- java集合之TreeSet的整理
- java集合框架之TreeSet类
- linux 常用指令
- androidのDOM方式解析XML
- 《Java并发编程实践》笔记6——并发性调优
- C++字符串操作集合
- 什么是Web缓存,为什么要使用它
- JAVA集合之——TreeSet
- BIN 转化为 S19 格式及 S19 格式解析
- CentOS 配置网络环境
- UNIX网络编程 卷2:进程间通信
- iOS代码文档化,比注释更高级!
- 纯虚函数和虚函数
- 我的第一篇技术BLOG
- unix环境高级编程---线程
- struts2通配符问题