java中treemap_Java中TreeMap集合讲解
1.TreeSet介绍
TreeSet是一个有序集合,可以以任意顺序将元素插入到集合中,在对集合进行遍历的时候,每个元素将自动按照排序后的顺序呈现。底层使用的是二叉树(更具体点是红黑树)实现,对于元素之间排序,如果不指定自定义的比较器Comparator,那么插入的对象必须实现Comparable接口,元素按照实现此接口的compareTo()方法去排序。如果指定了自定义的比较器Comparator,优先使用Comparator去对元素进行排序。比较规则决定了元素是否可以重复,以及元素的排序结果。
2.特点保存的元素按照一定的规则有序
可自定义排序规则
非线程安全
3.存储Integer类型元素import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>();
ts.add(1); //自动装箱
ts.add(7);
ts.add(3);
ts.add(5);
ts.add(3); //重复元素
System.out.println(ts);
}
}
输出:[1, 3, 5, 7]
看上面代码的输出,不仅输出元素有序,而且去除了重复元素3,我们在存元素的时候,并不是按照1,3,5,7的顺序存储的,但是遍历却是按照顺序排列的。为什么呢?
前面我们说过,TreeSet在存对象的时候,如果不指定自定义的比较器,那么存储的对象必须实现Comparable接口,好,我们去看下Integer类有没有实现此接口。public final class Integer extends Number implements Comparable {
//省略其他代码
//......
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
分析:
通过Integer源码可知,它满足TreeSet的要求,实现了Comparable接口中唯一的抽象方法compareTo(),在此方法内部又调用了一个compare()方法去定义比较规则,返回值是0,1,或者-1。前面说过,TreeSet底层是二叉树实现的,当存储元素的时候,会调用比较规则方法和二叉树上的元素一一比较,如果要插入的元素比当前元素小就到左子树去比较,如果比当前元素大,就到右子树去比较,直到当前元素的左或者右子树为空,就插入此元素。如果在比较过程中,出现当前元素等于要插入的元素,那么此元素不插入,例如上例中最后一个元素3被过滤掉了,这样也就保证了Set的元素唯一性。
自定义比较器
前面说过,如果我们自定义了比较器Comparator,那么集合会优先使用自定义的比较器去对元素进行排序,好,我们现在想让集合中的Integer元素按照倒序排列,应该如何实现呢?先来查看JDK文档:
上图中红框标注的构造方法就是我们需要的,这里需要传入一个Comparator接口类型的对象,我们当然可以自定义一个类然后实现Comparator接口,然后再new一个对象当作参数传入TreeSet()的构造方法,但是为了方便,我们使用匿名类实现。在此之前,我们先看下Comparator接口都有什么抽象方法。
此接口只有两个抽象方法,我们先不用管equals()方法,定义排序规则需要在compare()这个方法。好,我们来实现一下集合中元素倒序排序。import java.util.Comparator;
import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
if(o1 == o2) return 0;
return o1 < o2 ? 1 : -1;
}
});
ts.add(1); //自动装箱
ts.add(7);
ts.add(3);
ts.add(5);
ts.add(3);
System.out.println(ts);
}
}
输出:[7, 5, 3, 1]
分析:
1、读者可能发现,Comparator接口明明有两个抽象方法,为什么只实现了compare(),很简单。我们知道匿名类也是一个类,只要是类就会默认继承Object类,那么就会默认继承Object类的equals()方法,所以其实我们已经使用了从Object类继承的方法去实现了Comparator接口的equals()方法。
2、我们在compare()方法中定义了排序规则,和Integer类中实现的方式正好相反,小于返回1,大于返回-1,等于返回0,所以输出的元素就是倒序了。由于我们在TreeSet中自定义了比较器,所以Integer类的比较规则就失效了。
4.存储自定义对象Student类
public class Student implements Comparable{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>();
ts.add(new Student("张廷玉",43));
ts.add(new Student("纳兰明珠",80));
ts.add(new Student("索额图",79));
System.out.println(ts);
}
}
输出:
[Student [name=张廷玉, age=43], Student [name=索额图, age=79], Student [name=纳兰明珠, age=80]]
首先我们定义了一个Student类,前面说过,如果没有自定义比较器,TreeSet集合存储的对象元素必须实现Comparable接口,这里我们的Student类实现了此接口,并且实现了此接口的唯一抽象方法compareTo(),这里我们是按照学生年龄排序(升序)。如果这里不实现Comparable接口,那么会报 java.lang.ClassCastException异常,意思就是这里存的元素不是Comparable类型的。
自定义比较器
我们用自定义比较器来实现一个小案例。这里我们对学生首先按照年龄进行排序,如果年龄相同,我们再按照名字的长度进行排序,都是升序,来看看我们怎么实现它。public class Student{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
import java.util.Comparator;
import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() - o2.getAge();
return num == 0 ? o1.getName().length() - o2.getName().length() : num;
}
});
ts.add(new Student("张廷玉",43));
ts.add(new Student("纳兰明珠",80));
ts.add(new Student("索额图",79));
ts.add(new Student("苏麻喇姑",79));
for (Student student : ts) {
System.out.println(student);
}
}
}
输出:
Student [name=张廷玉, age=43]
Student [name=索额图, age=79]
Student [name=苏麻喇姑, age=79]
Student [name=纳兰明珠, age=80]
由于我们在TreeSet中自定义了比较器,这里的Student类不需要实现Comparable接口了。我们来看compare()方法内部,首先计算比较的元素的年龄差num,如果num不等于0,那么我们还是按照年龄排序,如果年龄相同,那么我们返回元素名字长度的差,也就是说年龄相同,我们按照名字长度进行排序。从输出可以看出,索额图和苏麻喇姑的年龄相同,但是索额图名字长度要小于苏麻喇姑,所以索额图排在了苏麻喇姑的前面输出。
至此!如何使用TreeSet去存储对象以及内部的排序原理我们就讲完了,有时间自己动手去实现一下,多思考为什么要这样,眼高手低是程序员一大忌讳。如果不懂的读者可以在下面留言!
java中treemap_Java中TreeMap集合讲解相关推荐
- [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具
原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.G ...
- js 中转换成list集合_程序员:java集合介绍-List,具说很详细,你不来看看?
Java集合介绍 作为一个程序猿,Java集合类可以说是我们在工作中运用最多.最频繁的类.相比于数组(Array)来说,集合类的长度可变,更加方便开发. Java集合就像一个容器,可以存储任何类型的数 ...
- Java中HashMap和TreeMap的区别深入理解,java开发面试笔试题
我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...
- Java 并发编程中的死锁 ( Kotlin 语言讲解)
什么是死锁? 在操作系统中的并发处理场景中, 进程对资源的持有与请求过程中,会产生死锁. Say, Process A has resource R1 , Process B has resource ...
- 在java商城开发中map集合的应用
在java商城开发中map集合的put方法(Object key, Object value)添加一个"值"(想要得东西)和与"值"相关联的"键&qu ...
- JAVA中希尔排序去的讲解_java 中基本算法之希尔排序的实例详解
java 中基本算法之希尔排序的实例详解 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shel ...
- MySQL 数据类型讲解 和Java中所对应的数据类型讲解
MySQL 数据类型讲解 和Java中所对应的数据类型讲解 Mysql数据类型分类 在Mysql中常用数据类型一共有四种字符串数据类型.日期/时间数据类型.数值数据类型以及二进制数据类型. 一.字符串 ...
- java backbone_[Java教程]移动前端开发中的Backbone之一:Backbone中的模型和集合
[Java教程]移动前端开发中的Backbone之一:Backbone中的模型和集合 0 2015-09-24 17:00:04 当我们开发含有大量Javascript的web应用程序时,首先你需要做 ...
- 【Java】如何理解Java中的双列集合Map?
1 Map<K,V>接口 1.1 特点 双列集合一个元素包含俩值 Key不可以重复,Value可以重复 Key和Value一一对应 Key和Value可以时任意类型 1.2 常用方法 pu ...
最新文章
- sql server2005 循环操作
- mysql 自连接 树形_自连接表的相关问题(树形结构)
- android 相册 标签,在Android标签上,如何在图片下方显示文字?
- MySQL学习记录—Date函数系列
- Google Chrome进入暗黑模式
- 一款用了都说好的思维导图软件:Ayoa
- 配置中文XeLaTex环境
- jQuery-点击按钮插入视频
- NPM_出现 ETIMEDOUT
- 昨晚 win7 盗版 黑屏了
- 今日头条面试题,供大家参考
- 3D或游戏画面卡顿的解决方法
- 百分六用计算机该怎么算,24975000的百分之五是多少,用计算器怎么算?
- 分布式、高并发、高性能场景(抢购、秒杀、抢票、限时竞答)数据一致性解决方案
- 微pe工具箱+软碟通 制作 U盘启动盘
- 两个usb摄像头通过hub连接电脑怎么同时独立显示_把电脑装进口袋是什么感觉?华硕VivoStick TS10多角度体验...
- 和谁在一起的确很重要
- 格子玻尔兹曼机(Lattice Boltzmann Method)系列3:LBM在不可压缩流动下的边界条件算法
- iOS 解决scoryboard上tableview、collection view顶部有空白问题
- 最完整VC++6.0安装教程、windows命令行cl编译命令配置、cl编译命令使用、以及整套安装所需的附件
热门文章
- 信息收集——指纹识别
- ButterKnife的简单使用
- php kml文件解析,英语翻译中文:详细分析了KML、MapInfo文件及二者之间的联系,以KML点标记文件为例,基于PHP编程实现了KML到...
- 外星人台式电脑_执掌游戏世界 外星人ALIENWARE m15丨17.9mm机身轻悍降临【电脑组装】公众号分享台式机笔记本电脑 京东商城特惠通道...
- @Url cannot be used with @GET URL (parameter #1)
- java 优化 寄存器_JVM性能优化系列-(6) 晚期编译优化
- html vw自动跳到ie,CSS3动画/关键帧,在IE11问题中使用vw进行转换
- java list 面试题_java【集合】面试题
- mysql change命令_Mysql 操作基本命令大全
- 正确使用stl map的erase方法