Java深入了解TreeSet
Java中的TreeSet是Set的一个子类,TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一。
那TreeSet为什么能保证元素唯一,它是怎样排序的呢?先看一段代码:
public static void demo() {
TreeSet<Person> ts = new TreeSet<>();
ts.add(new Person("张三", ));
ts.add(new Person("李四", ));
ts.add(new Person("周七", ));
ts.add(new Person("王五", ));
ts.add(new Person("赵六", ));
System.out.println(ts);
}
执行结果:
出错,会抛出一个异常:java.lang.ClassCastException
显然是出现了类型转换异常。原因在于我们需要告诉TreeSet如何来进行比较元素,如果不指定,就会抛出这个异常
如何解决:
如何指定比较的规则,需要在自定义类(Person)中实现```Comparable```接口,并重写接口中的compareTo方法
public class Person implements Comparable<Person> {
private String name;
private int age;
...
public int compareTo(Person o) {
return ; //当compareTo方法返回0的时候集合中只有一个元素
return ; //当compareTo方法返回正数的时候集合会怎么存就怎么取
return -; //当compareTo方法返回负数的时候集合会倒序存储
}
}
为什么返回0,只会存一个元素,返回-1会倒序存储,返回1会怎么存就怎么取呢?原因在于TreeSet底层其实是一个二叉树机构,且每插入一个新元素(第一个除外)都会调用```compareTo()```方法去和上一个插入的元素作比较,并按二叉树的结构进行排列。
1. 如果将```compareTo()```返回值写死为0,元素值每次比较,都认为是相同的元素,这时就不再向TreeSet中插入除第一个外的新元素。所以TreeSet中就只存在插入的第一个元素。
2. 如果将```compareTo()```返回值写死为1,元素值每次比较,都认为新插入的元素比上一个元素大,于是二叉树存储时,会存在根的右侧,读取时就是正序排列的。
3. 如果将```compareTo()```返回值写死为-1,元素值每次比较,都认为新插入的元素比上一个元素小,于是二叉树存储时,会存在根的左侧,读取时就是倒序序排列的。
利用上述规则,我们就可以按照年龄来排序了。代码如图
public int compareTo(Person o) {
int num = this.age - o.age; //年龄是比较的主要条件
return num == ? this.name.compareTo(o.name) : num;//姓名是比较的次要条件
}
按照姓名排序(依据Unicode编码大小),代码如下:
public int compareTo(Person o) {
int num = this.name.compareTo(o.name); //姓名是主要条件
return num == ? this.age - o.age : num; //年龄是次要条件
}
按照姓名长度排序,代码如下:
public int compareTo(Person o) {
int length = this.name.length() - o.name.length(); //比较长度为主要条件
int num = length == ? this.name.compareTo(o.name) : length; //比较内容为次要条件
return num == ? this.age - o.age : num; //比较年龄为次要条件
}
以上是TreeSet如何比较自定义对象,接下来我们再来看一下TreeSet如何利用比较器比较元素。
需求:现在要制定TreeSet中按照String长度比较String。
//定义一个类,实现Comparator接口,并重写compare()方法,
class CompareByLen /*extends Object*/ implements Comparator<String> { @Override
public int compare(String s1, String s2) { //按照字符串的长度比较
int num = s1.length() - s2.length(); //长度为主要条件
return num == ? s1.compareTo(s2) : num; //内容为次要条件
}
}
public static void demo4() {
//需求:将字符串按照长度排序
TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //Comparator c = new CompareByLen();
ts.add("aaaaaaaa");
ts.add("z");
ts.add("wc");
ts.add("nba");
ts.add("cba");
System.out.println(ts);
}
总结
- 特点
- TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
- 使用方式
- a.自然顺序(Comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型
- 调用对象的compareTo()方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
- b.比较器顺序(Comparator)
- 创建TreeSet的时候可以制定 一个Comparator
- 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中compare()方法排序
- 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
- c.两种方式的区别
- TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
- TreeSet如果传入Comparator, 就优先按照Comparator
- a.自然顺序(Comparable)
Java深入了解TreeSet的更多相关文章
- Java HashSet和TreeSet【笔记】
Java HashSet和TreeSet[笔记] PS:HashSet.TreeSet 两个类是在 Map 的基础上组装起来的类 HashSet 类注释 1.底层实现基于 HashMap,所以迭代时不 ...
- JAVA中的TreeSet
TreeSet简介 TreeSet是一个有序的集合,它的作用是提供一个有序的Set集合,它继承于AbstractSet抽象类实现了NavigableSet<E>, Cloneable, j ...
- java.util 类 TreeSet<E>
java.lang.Object≥ java.util.AbstractCollection<E> ≥ java.util.AbstractSet<E> ≥ java.util ...
- java 集合框架(TreeSet操作,自动对数据进行排序,重写CompareTo方法)
/*TreeSet * treeSet存入数据后自动调用元素的compareTo(Object obj) 方法,自动对数据进行排序 * 所以输出的数据是经过排序的数据 * 注:compareTo方法返 ...
- Java集合之TreeSet
TreeSet是一个有序的集合,它的作用是提供有序的Set集合.它继承了AbstractSet抽象类,实现了NavigableSet<E>,Cloneable,Serializable接口 ...
- 死磕 java集合之TreeSet源码分析
问题 (1)TreeSet真的是使用TreeMap来存储元素的吗? (2)TreeSet是有序的吗? (3)TreeSet和LinkedHashSet有何不同? 简介 TreeSet底层是采用Tree ...
- Java解惑之TreeSet是如何去重的
引言: 最近在处理一个问题,大致是这个样子,从数据库里面取出一个集合,取出来的数据放到一个JavaBean里面.结果得到的集合长度为1. TreeSetSet的一个实现,默认实现排序:故TreeSet ...
- 详解java中的TreeSet集合
TreeSet是实现Set接口的实现类.所以它存储的值是唯一的,同时也可以对存储的值进行排序,排序用的是二叉树原理.所以要理解这个类,必须先简单理解一下什么是二叉树. 二叉树原理简述 假如有这么一个集 ...
- Java——HashSet和TreeSet的区别
HashSetHashSet有以下特点 不能保证元素的排列顺序,顺序有可能发生变化 不是同步的 集合元素可以是null,但只能放入一个null当向HashSet集合中存入一个元素时,HashSe ...
随机推荐
- kindeditor用法简单介绍
最近做毕业设计用了一个叫做kindeditor的文本编辑工具,相信很多人都用过,这货和fckeditor差不多,个人感觉这个的皮肤更好看,而且对中文的支持更好,没那么容易出现中文乱码问题.下次记录一下 ...
- ubuntu连接android设备(附最简单方法)
在ubuntu下连接android设备,虽然不用像windows那样安装驱动,然而却会遇见一个错误:输入adb shell,会提示insufficient permissions for device ...
- android最新更新方法
使用SDK Manager更新时出现问题Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-6.xm ...
- Activity与Fragment的生命周期详解
在安卓中Activity与Fragment是非常相似的两个类,它们各自都拥有自己的生命周期,且都可以用来显示布局文件中的视图.其中Activity是通过setContenView()显示视图,而Fra ...
- (NO.00004)iOS实现打砖块游戏(二):实现游戏主界面动画
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 一个内容不错的游戏也要一个好的包装.玩家进入游戏时第一眼看到的是 ...
- iOS开发基础block的形式讲解
前几个星期,我利用通知写了一个仿京东选择地址的Demo(http://blog.csdn.net/hbblzjy/article/details/52212879),后来看过一篇文章说,尽量少用通知, ...
- Android进阶(十)Android 发邮件
最近在做的APP涉及到发邮件,总结如下: 在android里进行邮件客户端开发可以有两种方式: 在邮件客户端的设计中,可以采用两种方法. 一种是调用android系统自带的邮件服务 优点:这种方法比较 ...
- H5学习之旅-H5的新特性(1)
随着H5的发展,网页开发呈现了跨平台的特性,目前H5是兼容各大平台的,这也为一些其他的技术的跨平台开发提供了基础,所以我预测后H5会成为很重要的开发语言 新特性介绍 1.用于回话的canvas标签 2 ...
- css3动画从入门到精通
什么是css3动画? 通过 CSS3,我们能够创建动画,这可以在许多网页中取代动画图片.Flash 动画以及 JavaScript. CSS3带来了圆角,半透明,阴影,渐变,多背景图等新的特征,轻松实 ...
- 【网站搭建】搭建独立域名博客 -- 独立域名博客上线了 www.hanshuliang.com
博客是安装在阿里云的服务器上. 小结 : -- 进入数据库命令 :mysql -uroot -p123456 ; -- 检查nginx配置语法 :.../nginx/sbin/nginx -t; -- ...