Set集合TreeSet学习(Set集合学习二)
来源:互联网 发布:mac顶部菜单栏截图工具 编辑:程序博客网 时间:2024/06/08 11:30
Set集合TreeSet学习(Set集合学习二)
4、TreeSet: 可以对Set集合中的元素进行排序。是不同步的
4.1、TreeSet保证元素唯一的方式
TreeSet使用元素的自然顺序(字典顺序)对元素进行排序【TreeSet集合排序方式一:让元素自身具备比较功能】
或者
根据创建 set 时提供的 Comparator (比较器)进行排序,具体取决于使用的构造方法。【TreeSet集合排序方式二:让集合自身具备比较功能】
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
(1)TreeSet集合排序方式一:让元素自身具备比较功能
让元素自身具备比较功能,只就需要实现Comparable接口。覆盖compareTo方法。【Comparable接口的compareTo方法】
即:自定义对象实现Comparable接口,定义排序方式,实现comparaTo方法。
(2)特殊场景分析
场景:
如果不要按照对象中具备的自然顺序进行排序,怎么办?
对象不是自己的定义的,而是使用别人定义好的,我们不能对这个对象做任何修改,而且这个对象没有实现Comparable接口,怎么办?
这个对象不具有比较性!或者说,这个对象具备比较性,实现了Comparable接口,但是这个对象具备的比较性,不是我们需要的,我们该怎么办?
解决方案:
使用TreeSet集合排序方式二:让集合自身具备比较功能
(3)TreeSet集合排序方式二:让集合自身具备比较功能
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
4.2、TreeSet集合使用注意
(1)TreeSet集合排序方式一:让元素自身具备比较功能
【1】当元素为自定义对象(eg:Person类)时,让元素自身具备比较功能,实现Comparable接口,覆盖compareTo方法
【2】当元素为字符串对象(eg:“abd”)或者jdk中的对象有实现Comparable接口的方法时,由于这些对象本身已经实现了Comparable接口的compareTo方法,本身就具备比较功能,直接使用TreeSet即可。
(2)TreeSet集合排序方式二:让集合自身具备比较功能
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
public TreeSet(Comparator<? super E>comparator)构造时传递参数
构造一个新的空 TreeSet,它根据指定比较器进行排序。插入到该 set 的所有元素都必须能够由指定比较器进行相互比较:对于 set 中的任意两个元素 e1 和 e2,执行 comparator.compare(e1, e2) 都不得抛出 ClassCastException
(3)排序优先
当TreeSet集合使用时,如果元素本身具备比较功能;
然后又定义一个类实现Comparator接口,覆盖compare方法,并该类对象作为参数传递给TreeSet集合的构造函数。使得TreeSet集合自身具备比较功能。
这时候,TreeSet的排序方法以集合自身具备的比较功能为主(即:TreeSet集合排序方式二为主,忽略TreeSet集合排序方式一)
结论:当TreeSet集合有两种比较功能时,TreeSet集合排序方式二(集合自身具备比较功能)优先于 TreeSet集合排序方式一(元素本身具备比较功能)
4.3、TreeSet集合排序案例
(1)TreeSet集合排序方式一案例:
让元素自身具备比较功能
代码实现:
【1】集合排序1测试类
packagelist_set;importjava.util.Iterator;importjava.util.TreeSet;/* * TreeSet集合排序方式一: * 让元素自身具备比较功能,就需要实现Comparable接口。覆盖compareTo方法。 */ public class TreeSetFirst { public static void main(String[] args) { TreeSet set=new TreeSet(); set.add(new Person("张三",23)); set.add(new Person("张三",23));//去除重复 让元素自身具备比较功能 set.add(new Person("李四",24));//去除重复 set.add(new Person("李四",24)); set.add(new Person("王五",24)); set.add(new Person("赵六",25)); set.add(new Person("你好",26)); //遍历 for(Iterator it=set.iterator();it.hasNext();){ Person p=(Person)it.next(); System.out.println(p.getName()+":"+p.getAge()); } }}
【2】Person自定义对象
/* * 让person元素本身具备比较功能 * 实现Comparable接口。覆盖compareTo方法。 */class Person implements Comparable{ private String name; private int age; public Person(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; } @Override public int compareTo(Object o) {//定义比较方式 /* *1.年纪小的排在前面 *2.当年纪相同是,名字的自然排序小于0的排在前面 */ Person p=(Person)o; int ageCompare=this.getAge()-p.getAge(); if(ageCompare==0){ //小于0 在前;等于0 相等;大于0 在后 return this.getName().compareTo(p.getName());//自然排序// returnthis.name.hashCode()-p.name.hashCode();//hashcode值 } return ageCompare;//小于0 在前;大于0 在后 } }
结果:
张三:23
李四:24
王五:24
赵六:25
你好:26
(2)TreeSet集合排序方式二案例:
让集合自身具备比较功能
代码实现:
【1】自定义比较器
/* * 自定义比较器实现Comparator接口,覆盖compare方法。 */class MyComparator implements Comparator { @Override public int compare(Object o1, Object o2) { /* *1.年纪小的排在前面 2.当年纪相同是,名字的自然排序小于0的排在前面 */ Person p1 = (Person) o1; Person p2 = (Person) o2; int ageCompare = p1.getAge() - p2.getAge(); if (ageCompare == 0) { return p1.getName().compareTo(p2.getName());//自然排序// return p1.getName().hashCode() -p2.getName().hashCode();//hashcode值 // 小于0 在前;等于0相等;大于0在后 } return ageCompare;// 小于0 在前;大于0 在后 } }
【2】集合排序2测试类
packagelist_set;importjava.util.Comparator;importjava.util.Iterator;importjava.util.TreeSet; /* * TreeSet集合排序方式二: * 让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。 * 将该类对象作为参数传递给TreeSet集合的构造函数。 */public class TreeSetSecond { public static void main(String[] args) { TreeSet set = new TreeSet(new MyComparator());//调用自定义比较器,让集合自身具备比较功能 set.add(new Person("张三", 23)); set.add(new Person("张三", 23));// 去除重复让集合自身具备比较功能 set.add(new Person("李四", 24));// 去除重复 set.add(new Person("李四", 24)); set.add(new Person("王五", 24)); set.add(new Person("赵六", 25)); set.add(new Person("你好", 26)); // 遍历 for (Iterator it = set.iterator(); it.hasNext();) { Person p = (Person) it.next(); System.out.println(p.getName() + ":" + p.getAge()); } }}
结果:
张三:23
李四:24
王五:24
赵六:25
你好:26
4.4、TreeSet集合排序规则的分析
参考博客园
博文:Java深入了解TreeSet
地址:http://www.cnblogs.com/yzssoft/p/7127894.html
(1)代码
packagelist_set; /* * 让person元素本身具备比较功能 * 实现Comparable接口。覆盖compareTo方法。 */class Persons implements Comparable { private String name; private int age; public Persons(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; } @Override public int compareTo(Object o) {// 定义比较方式 return 0; // 当compareTo方法返回0的时候集合中只有一个元素// return 1; // 当compareTo方法返回正数的时候集合会怎么存就怎么取// return -1; // 当compareTo方法返回负数的时候集合会倒序存储 } }
(2)代码现象分析
为什么返回0,只会存一个元素,返回-1会倒序存储,返回1会怎么存就怎么取呢?
原因:在于TreeSet底层其实是一个二叉树机构,且每插入一个新元素(第一个除外)都会调用compareTo()的方法去和上一个插入的元素作比较,并按二叉树的结构进行排列。
1. 如果将compareTo()方法的返回值固定为0,元素值每次比较,都认为是相同的元素,这时就不再向TreeSet中插入除第一个外的新元素。所以TreeSet中就只存在插入的第一个元素。
2. 如果将compareTo()方法的返回值固定为1,元素值每次比较,都认为新插入的元素比上一个元素大,于是二叉树存储时,会存在根的右侧,读取时就是正序排列的。
3. 如果将compareTo()方法的返回值固定为-1,元素值每次比较,都认为新插入的元素比上一个元素小,于是二叉树存储时,会存在根的左侧,读取时就是倒序排列的。
(3)结论
同理,Comparator(比较器)的compare方法返回结果和Comparable接口的compareTo方法返回结果的正负情况,决定了TreeSet集合的排序情况
返回结果为正数时,当前元素,比上一个元素大
返回结果为负数时,当前元素,比上一个元素小
返回结果为0时,当前元素和上一个元素相同。
(4)三种情况案例
1情况一:CompareTo方法中,直接返回return 0(集合只有一个元素)
1.1compareTo方法
public int compareTo(Object o) {// 定义比较方式 return 0; // 当compareTo方法返回0的时候集合中只有一个元素}
1.2测试代码
packagelist_set; importjava.util.Iterator;importjava.util.TreeSet; public class Test1 { public static void main(String[] args) { TreeSet set=new TreeSet(); set.add(new Persons("张三",23)); set.add(new Persons("李四",24)); set.add(new Persons("王五",24)); set.add(new Persons("赵六",25)); set.add(new Persons("你好",26)); //遍历 for(Iterator it=set.iterator();it.hasNext();){ Persons p=(Persons)it.next(); System.out.println(p.getName()+":"+p.getAge()); } } }
1.3结果【只有一个元素】
张三:23
2 情况二:CompareTo方法中,直接返回return 1(集合正序排列)
2.1compareTo方法
public int compareTo(Object o) {// 定义比较方式 return 1; // 当compareTo方法返回正数的时候集合会怎么存就怎么取 }
2.2测试代码
同:三种情况案例的情况一中的4.1.2测试代码
2.3结果【正序输出】
张三:23
李四:24
王五:24
赵六:25
你好:26
3 情况三:CompareTo方法中,直接返回return -1(集合逆序排列)
3.1compareTo方法
public intcompareTo(Object o) {// 定义比较方式 return -1; // 当compareTo方法返回负数的时候集合会倒序存储 }
3.2测试代码
同:三种情况案例的情况一中的4.1.2测试代码
3.3结果【逆序输出】
你好:26
赵六:25
王五:24
李四:24
张三:23
4.5、应用:对字符串进行长度排序
(1)字符串长度比较器
packagelist_set; importjava.util.Comparator;/* * 字符串长度比较器 */public class ComparatorByLength implements Comparator { @Override public int compare(Object o1, Object o2) { //1.先比较字符串长度,如果长度不同,则比较结束,否则,进入2 //2.比较字符串的字典顺序 String s1=(String)o1; String s2=(String)o2; int temp=s1.length()-s2.length(); return temp==0?s1.compareTo(s2):temp; } }
(2)字符串长度排序测试
packagelist_set;importjava.util.Iterator;importjava.util.TreeSet;/* * 对字符串进行长度排序 */public class CompareByLengthTest { public static void main(String[] args) { TreeSetts = new TreeSet(new ComparatorByLength());//字符串长度排序比较器 ts.add("aaaaa"); ts.add("zz"); ts.add("nbaq"); ts.add("cba"); ts.add("abc"); Iterator it = ts.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
(3)结果
zz
abc
cba
nbaq
aaaaa
4.6思考:TreeSet怎么存进去?怎么取出来?
存:按照TreeSet的两种排序方式的其中一种进行排序,详情看:TreeSet集合排序规则的分析
取:从二叉树的最左端的开始取,然后按照【左子树,右子树,父节点】顺序进行取元素。依次类推,进行取,直到结束
- Set集合TreeSet学习(Set集合学习二)
- Set集合HashSet,TreeSet
- JAVA学习第三十七课(常用对象API)— Set集合:TreeSet集合、比较器
- JAVA学习.JAVA集合类型Collection.Set.HashSet&TreeSet
- Set集合HashSet学习(Set集合学习一)
- 09.集合框架(二)【Set】【HashSet】【TreeSet】
- Set接口(Set接口简介、HashSet集合、TreeSet集合 )
- set集合入门学习
- JAVA学习笔记(二十一)- 集合 Set
- stl学习(二)集合 set 的使用
- java日常学习:集合(二)list和set接口
- Set集合:HashSet、TreeSet、泛型
- 【insigma】集合Set (HashSet、TreeSet)
- Java集合框架-Set(TreeSet)
- Java Set集合之Treeset
- Java基础--集合Set-TreeSet
- Java--集合(Set:HashSet,TreeSet)
- 集合框架__【Set集合】【HashSet】【TreeSet】
- java日常学习:异常和finally块
- 【Unity】图形渲染优化、渲染管线优化、图形性能优化
- 三元表达式
- springmvc 执行@Test报错
- 二叉树的一系列基本操作
- Set集合TreeSet学习(Set集合学习二)
- 使用Gradle构建Android应用
- React菜鸟教程学习笔记
- 算法——背包问题 01背包+完全背包+多重背包
- 论「版本号」的正确使用方式
- Oracle之block能装多少行?以及dbms_rowid包讲解
- 初始R语言——决策树
- mybatis详细配置
- orcale对应java关系