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<Integer> 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<Integer> {//省略其他代码//......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<Integer> ts = new TreeSet<>(new Comparator<Integer>() {@Overridepublic 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<Student>{private String name;private int age;public Student(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Student o) {return this.age - o.age;}
}
import java.util.TreeSet;
public class DemoTreeSet {public static void main(String[] args) {TreeSet<Student> 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;}@Overridepublic 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<Student> ts = new TreeSet<>(new Comparator<Student>() {@Overridepublic 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去存储对象以及内部的排序原理我们就讲完了,有时间自己动手去实现一下,多思考为什么要这样,眼高手低是程序员一大忌讳。如果不懂的读者可以在下面留言!
转载于:https://www.cnblogs.com/neuzk/p/9476418.html
Java中TreeMap集合讲解相关推荐
- java中treemap_Java中TreeMap集合讲解
1.TreeSet介绍 TreeSet是一个有序集合,可以以任意顺序将元素插入到集合中,在对集合进行遍历的时候,每个元素将自动按照排序后的顺序呈现.底层使用的是二叉树(更具体点是红黑树)实现,对于元素 ...
- 万字长文深入理解java中的集合-附PDF下载
文章目录 1. 前言 2. List 2.1 fail-safe fail-fast知多少 2.1.1 Fail-fast Iterator 2.1.2 Fail-fast 的原理 2.1.3 Fai ...
- java中各种集合的用法和比较
一,java中各种集合的关系图 Collection 接口的接口 对象的集合 ├ List 子接口 按进入先后有序保存 可重复 │├ L ...
- java中的集合_Java 集合介绍,常用集合类
JAVA 集合 在处理数据的过程中经常会需要一个容器来存储某一类型的数据,Java 中的数组就是这样一种容器.但 Java 中的数组有其局限性,定义后的数组长度不可变,超出数组长度后就不能再存放数据了 ...
- Java中List集合的三种遍历方式(全网最详)
Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...
- 10.JAVA中的集合(数据结构)
Java中的集合 包含以下结构: 数组-线性表 链表 栈 队列 散列表 二叉树 映射关系(key-value) List集合 特点:[有序.重复] [线性表--数组] ArrayList 定义 线程 ...
- Java中哪些集合是有序的?
Java中哪些集合是有序的? 实现了 List 接口的集合类全部有序:比如ArrayList.LinkedList LinkedHashMap:在 HashMap 的基础上多维护了一个双向链表. Co ...
- java list 前100个_实现java 中 list集合中有几十万条数据,每100条为一组取出
解决"java 中 list集合中有几十万条数据,每100条为一组取出来如何实现,求代码!!!"的问题. 具体解决方案如下: /** * 实现java 中 list集合中有几十万条 ...
- Java中的集合浅析
java中的集合就像是一个容器一样,专门用来存储java对象的引用,这些对象可以是任意的数据类型并且长度可变,集合类位于java.util包中. java集合按照其存储结构可以分为两大类,一个是单列集 ...
- Java实现TreeMap集合的排序:Key键的升序与降序、Value值的排序
Java 提供的 Map 接口常用的实现类有 HashMap 和 TreeMap.HashMap 类实现的 Map 集合对于添加和删除映射关系效率更高.HashMap 通过哈希码对其内部的映射关系进行 ...
最新文章
- 揭秘星际2人工智能AlphaStar:DeepMind科学家回应一切
- Platforms/iPhoneSimulator.platform/Developer/usr/bin/g++-4.2 failed with exit code 1问题总结及解决方案...
- “is”与“==”区别
- 看过这五条,再离职!
- 从双层优化视角理解对抗网络GAN
- Matlab多个Figure图合成一个Fig
- 小米12 Ultra或将在5月发布:依旧为骁龙8移动平台
- choices相当于实现一个简化版的外键
- Android8.0、9.0、10.0、11.0的新特性兼容适配代码修改
- python入门——P44魔法方法:简单定制
- 如何突破织梦后台发布文章的250字符的内容摘要字数限制
- 中英文论文写作指导第三部分(实验、材料和方法部分)
- 【压力测试】用JMeter进行百科网站压力测试
- 别人是怎么将图片贴在屏幕上的?
- 毕业设计 -- 微信小程序选题大全(一)
- 【ZJOI2005】沼泽鳄鱼
- 细说上帝视角游戏的快速创建
- 在UBUNTU中使用北通USB游戏手柄
- 智能运维案例系列 | 新网银行 X 袋鼠云:银行核心业务系统日志监控平台建设实践...
- win系统录音设备无法正常录音解决方案之一
热门文章
- 【渝粤教育】国家开放大学2018年春季 8662-22T特色课(1) 参考试题
- [渝粤教育] 广东-国家-开放大学 21秋期末考试互联网营销概论10092k2
- 【渝粤教育】电大中专电商运营实操 (12)作业 题库
- 【渝粤教育】国家开放大学2018年春季 3818-21T燃气工程施工 参考试题
- 软件类配置(三)【ubuntu16.04安装微软的AirSim自动驾驶仿真平台,并初步使用仿真。】
- 求解偏微分方程开源有限元软件deal.II学习--Step 48
- Hibernate---配置文件
- MSDN官方数据库开发群
- 表级约束和列级约束(二十)
- SQLServer2005/2008新的高效分页方法-row_number()over函数的使用