TreeSet
TreeSet集合存储元素特点:
1 无序不可重复,但是储存的元素可以按照大小顺序排序!称为可排序集合。
2 无序:这里的无序指的是存进去的顺序和取出来的顺序不同。并且没有下标。
1 TreeSet集合底层实际上是一个TreeMap
2 TreeMap集合底层是一个二叉树
3 放到TreeSet中的元素,等同于放到TreeMap集合key部分了。
4 TreeSet集合中的元素:无序,不可重复,但是可以按照元素的大小顺序自动排序。
称为:可排序集合。
对自定义的类型来说,TreeSet可以排序吗?
以下程序中对于Person来说,无法排序。因为没有指定Person对象之间的比较规则。
谁大谁小没有说明啊。
以下程序运行的时候出现了这个异常:
java.lang.ClassCastException
class com.javaSe.HashSet.Person cannot be cast to class java.lang.Comparable
出现这个异常的原因是:
Person类没有实现java.lang.Comparable接口。
TreeSet集合中元素可排序的第二种方式:使用比较器的方式
最终的结论:
方法TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:
第一种:放在集合中的元素实现java.lang.Comparable接口
第二种:在构造TreeSet或者TreeMap集合的时候给他传一个比较器对象。Comparator
Comparator 和 Comparable 怎么选择呢?
当比较规则不会发生改变的时候,或者说当比较规则只有一个的时候,建议实现Comparable接口。
如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
Comparator接口的设计符合OCP原则。
案例1:
package com.javaSe.HashSet; import java.util.Set; import java.util.TreeSet; /* TreeSet集合存储元素特点: 1 无序不可重复,但是储存的元素可以按照大小顺序排序!称为可排序集合。 2 无序:这里的无序指的是存进去的顺序和取出来的顺序不同。并且没有下标。 */ public class TreeSetTest01 { public static void main(String[] args) { // 创建TreeSet集合 Set<String> strs = new TreeSet<>(); // 添加元素 strs.add("567"); strs.add("678"); strs.add("789"); strs.add("123"); strs.add("234"); strs.add("456"); strs.add("567"); strs.add("678"); strs.add("789"); strs.add("123"); strs.add("234"); strs.add("456"); // 遍历 for (String s : strs){ System.out.println(s); } } }
案例2:
package com.javaSe.HashSet; import java.util.TreeSet; /* 1 TreeSet集合底层实际上是一个TreeMap 2 TreeMap集合底层是一个二叉树 3 放到TreeSet中的元素,等同于放到TreeMap集合key部分了。 4 TreeSet集合中的元素:无序,不可重复,但是可以按照元素的大小顺序自动排序。 称为:可排序集合。 */ public class TreeSetTest02 { public static void main(String[] args) { // 创建一个TreeSet集合 TreeSet<String> ts = new TreeSet<>(); // 添加String ts.add("zhangsan"); ts.add("list"); ts.add("wangwu"); ts.add("liuliu"); ts.add("zhaoqi"); // 遍历 for (String s : ts){ // 按照字段顺序,升序排列 System.out.println(s); } TreeSet<Integer> ts1 = new TreeSet<>(); ts1.add(123); ts1.add(44); ts1.add(22); ts1.add(11); ts1.add(45); ts1.add(88); for (Integer i : ts1){ // 升序 System.out.println(i); } } } /* 数据库中有很多数据: userid name birth ----------------------------------- 1 zs 2019-01-11 2 ls 2019-02-11 3 ww 2019-03-11 4 ll 2019-04-11 编写程序从数据库当中取出数据,在页面展示用户信息的时候按照生日升序或者降序 这个时候可以使用TreeSet集合,因为TreeSet集合放进去,拿出来就是有顺序的。 */
案例3:
package com.javaSe.HashSet; import java.util.TreeSet; /* 对自定义的类型来说,TreeSet可以排序吗? 以下程序中对于Person来说,无法排序。因为没有指定Person对象之间的比较规则。 谁大谁小没有说明啊。 以下程序运行的时候出现了这个异常: java.lang.ClassCastException class com.javaSe.HashSet.Person cannot be cast to class java.lang.Comparable 出现这个异常的原因是: Person类没有实现java.lang.Comparable接口。 */ public class TreeSetTest03 { public static void main(String[] args) { Person p1 = new Person(22); Person p2 = new Person(11); Person p3 = new Person(44); Person p4 = new Person(10); // 创建TreeSet集合 TreeSet<Person> person = new TreeSet<>(); // 添加元素 person.add(p1); person.add(p2); person.add(p3); person.add(p4); for (Person s : person){ System.out.println("Person[age=" + s + "]"); } } } class Person{ int age; public Person() { } public Person(int age) { this.age = age; } @Override public String toString() { return "Person{" + "age=" + age + '}'; } }
案例4:
package com.javaSe.HashSet; import java.util.TreeSet; public class TreeSetTest04 { public static void main(String[] args) { Customer p1 = new Customer(22); Customer p2 = new Customer(11); Customer p3 = new Customer(44); Customer p4 = new Customer(10); // 创建TreeSet集合 TreeSet<Customer> customer = new TreeSet<>(); // 添加元素 customer.add(p1); customer.add(p2); customer.add(p3); customer.add(p4); for (Customer s : customer){ System.out.println(s); } } } // 需要在TreeSet集合中的元素需要时间java.lang.Comparable接口。 // 并且实现compareTo方法。equals可以不写。 class Customer implements Comparable<Customer>{ int age; public Customer() { } public Customer(int age) { this.age = age; } // 需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较! // k.compareTo(t.key) // 拿着参数k和集合中的每一个k进行比较,返回值可能是>0 <0 =0 都有可能 // 比较规则最终还是由程序员指定的,按照年龄升序。或者按照年龄降序。 public int compareTo(Customer o) {// c1.compareTo(c2); // this是c1 // c是c2 // c1 和 c2比较的时候,就是this和c比较 int age1 = this.age; int age2 = o.age; // 菜鸟的写法 /*if(age1 == age2){ return 0; } else if(age1 > age2) { return 1; } else { return -1; }*/ return o.age - this.age; // = 0 >0 <0 } public String toString() { return "Customer[" + "age=" + age + "]"; } }
案例5:
package com.javaSe.HashSet; import java.util.TreeSet; /* 先按照年龄升序,如果年龄一样的,再按照姓名升序 */ public class TreeSetTest05 { public static void main(String[] args) { TreeSet<Vip> vips = new TreeSet<>(); vips.add(new Vip("张三",20)); vips.add(new Vip("李四",10)); vips.add(new Vip("王五",30)); vips.add(new Vip("刘六",6)); for(Vip v : vips){ System.out.println(v); } } } class Vip implements Comparable<Vip>{ String name; int age; public Vip(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Vip{" + "name='" + name + '\'' + ", age=" + age + '}'; } /* compareTo方法的返回值很重要: 返回0表示相同,Value会覆盖 返回>0,会继续在右子树上找。【10 - 9 = 1,1 > 0的说明左边的数字比较大。所以在右边找。】 返回<0,会继续在左子树上找。 */ public int compareTo(Vip v) { // 写排序规则,按照什么进行比较。 if(this.age == v.age){ // 年龄相同时,按照姓名排序 // 姓名是String类型,可以直接比,调用compareTo来完成比较 return this.name.compareTo(v.name); } else { // 年龄不一样 return this.age - v.age; } } }
案例6:
package com.javaSe.TreeSet; import java.util.Comparator; import java.util.TreeSet; /* TreeSet集合中元素可排序的第二种方式:使用比较器的方式 最终的结论: 方法TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式: 第一种:放在集合中的元素实现java.lang.Comparable接口 第二种:在构造TreeSet或者TreeMap集合的时候给他传一个比较器对象。Comparator Comparator 和 Comparable 怎么选择呢? 当比较规则不会发生改变的时候,或者说当比较规则只有一个的时候,建议实现Comparable接口。 如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。 Comparator接口的设计符合OCP原则。 */ public class TreeSetTest06 { public static void main(String[] args) { // 创建TreeSet集合的时候,需要使用这个比较器。 // TreeSet<WuGui> wuGuis = new TreeSet<>();// 这样不行,没有通过构造方法传递一个比较器进去。 // 给构造方法传递一个比较器。 // TreeSet<WuGui> wuGuis = new TreeSet<>(new WuGuiiComparator()); // 大家可以使用匿名内部类的方式(这个类没有名字,直接new接口。) TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() { public int compare(WuGui o1, WuGui o2) { return o1.age - o2.age; } }); wuGuis.add(new WuGui(1000)); wuGuis.add(new WuGui(800)); wuGuis.add(new WuGui(900)); wuGuis.add(new WuGui(666)); for(WuGui wgs : wuGuis){ System.out.println(wgs); } } } // 乌龟 class WuGui{ int age; public WuGui(int age){ this.age = age; } public String toString() { return "小乌龟[" + "age=" + age + ']'; } } // 单独在这里编写一个比较器 // 比较器实现java.util.Comparator接口。(Comparable是java.lang包下的。Comparator是java.util包下的。) /* class WuGuiiComparator implements Comparator<WuGui> { public int compare(WuGui o1, WuGui o2) { // 指定比较规则 // 按照年龄排序 return o1.age - o2.age; } }*/