当前位置:   article > 正文

Java集合详解——TreeSet集合的介绍及其排序_treeset排序原理

treeset排序原理

一、TreeSet集合的自动排序

TreeSet集合的继承结构图

1、TreeSet集合使用红黑树数据结构实现元素的排序和存储,底层实际上是一个TreeMap集合

2、Tree Map集合底层实际上是一个二叉树。

3、放到TreeSet集合中的元素,等同于放到TreeMap集合中去了。

4、放到TreeSet集合中的元素:有序且唯一,即不可重复,有序是指可以按照元素的大小顺序自动排序。

5、TerrSet不允许插入null 元素,否则报空指针异常。

6、高效性能: 由于底层数据结构的特点,TreeSet 提供了高效的插入、删除和查找操作。它的时间复杂度通常是 O(log n),其中 n 是集合的大小。

7、可导航性: TreeSet 提供了一系列方法,如 first()、last()、lower()、higher()、ceiling()、floor() 等,用于在集合中查找元素或获取与给定元素最接近的元素。

8、不可变性: TreeSet 是不可变的集合,一旦创建,它的内容不可修改。如果需要对集合进行修改,可以创建一个新的 TreeSet 并复制元素。

TreeSet集合的常用构造方法
方法名描述
TreeSet()
构造一个新的空 TreeSet 集合,根据其元素的自然顺序进行排序
TreeSet(Comparator<?
super E> comparator)
构造一个新的空 TreeSet 集合,根据指定的比较器进行排序
TreeSet(Collection<?
extends E> c)
构造一个新的 TreeSet 集合,,该 TreeSet 集合包含指 定集合中的元素,并根据其元素的自然顺序进行排序。
  1. import java.util.*;
  2. public class test03 {
  3. public static void main(String[] args) throws Exception {
  4. TreeSet<String> ts = new TreeSet<>();
  5. ts.add("a");
  6. ts.add("b");
  7. ts.add("zhangsan");
  8. ts.add("laoliu");
  9. ts.add("老六");
  10. ts.add("zhangss");
  11. // 字符串默认重写了compare方法
  12. for (Object i:ts) {
  13. System.out.println(i);
  14. }
  15. System.out.println("--------------------------");
  16. TreeMap tm = new TreeMap();
  17. tm.put(1,"zhangsan");
  18. tm.put(2,"lisi");
  19. tm.put(2,"liss");
  20. tm.put(3,"lisi");
  21. Set<Map.Entry> set = tm.entrySet();
  22. for (Map.Entry i:set) {
  23. System.out.println(i);
  24. }
  25. }
  26. }

运行结果:  a
                    b
                    laoliu
                    zhangsan
                    zhangss
                    老六
                    --------------------------
                    1=zhangsan
                    2=liss
                    3=lisi

9、放到TreeSet或者TreeMap集合key部分中的元素要想做到排序,包括两种方式:

  • 第一种:放在集合中的元素实现java.lang.Comparable接口

  • 第二种:在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象

    • 下面就分别介绍一下这两种方式的实现。

二、TreeSet集合自定义类型排序

TreeSet集合无法对自定义类型排序:出现这种情况的原因是没有实现java.lang.comParable接口

这里的排序规则可参考下图所示的自平衡二叉树的讲解原理:

自平衡二叉树的图示

 所以需要实现comParable接口,代码实现如下所示:

  1. import java.util.*;
  2. public class test03 {
  3. public static void main(String[] args){
  4. person p = new person(12);
  5. person p1 = new person(52);
  6. person p2 = new person(102);
  7. person p3 = new person(92);
  8. TreeSet ts = new TreeSet<>();
  9. ts.add(p);
  10. ts.add(p1);
  11. ts.add(p2);
  12. ts.add(p3);
  13. for (Object i:ts ) {
  14. System.out.println(i);
  15. }
  16. }
  17. }
  18. //放在Treeset集合中的元素需要实现comParable接口。
  19. //并且实现comParaTo方法,equals可以不写。。
  20. class person implements Comparable<person>{
  21. int age;
  22. public person(int age){
  23. this.age=age;
  24. }
  25. //需要重写这个方法,编写比较的逻辑或规则,
  26. //k.comParaTo(t.key)
  27. //拿着参数k和集合中的每一个key进行比较,返回值可能是>0,<0,=0;
  28. //比较规则最终还是由程序员决定:例如按年龄升序或者降序。
  29. @Override
  30. public int compareTo(person c) {//c1.comParaTo(c2);
  31. //this是c1
  32. //c是c2
  33. //c1和c2比较的时候,就是this和c比较
  34. /* int age1 = this.age;
  35. int age2 = c.age;
  36. if (age1 ==age2){
  37. return 0;
  38. } else if (age1 >age2) {
  39. return 1;
  40. } else{
  41. return -1;
  42. }*/
  43. //也可以直接写成下面的这种形式
  44. //return this.age-c.age;// =,<0,>0 升序
  45. return c.age-this.age; //降序
  46. }
  47. public String toString(){
  48. return "person[age="+age+"]";
  49. }
  50. }

运行结果:person[age=12]

                 person[age=52]

                 person[age=92]

                 person[age=102]

三、TreeSet集合中的元素可排序的第二种方式:使用比较器的方式。 

  1. import java.util.*;
  2. //排序的第二种方式:使用比较器的方式
  3. public class test03 {
  4. public static void main(String[] args){
  5. person p = new person(12);
  6. person p1 = new person(52);
  7. person p2 = new person(102);
  8. person p3 = new person(92);
  9. //创建TreeSet集合的时候,一定要给构造方法传递一个比较器
  10. TreeSet<person> ts = new TreeSet<>(new PersonComparator());
  11. //这里也可以使用创建匿名内部类的方式:
  12. /*TreeSet<person> ts = new TreeSet<>(new Comparator<person>(){
  13. @Override
  14. public int compare(person o1, person o2) {
  15. return o1.age - o2.age;
  16. }
  17. });*/
  18. ts.add(p);
  19. ts.add(p1);
  20. ts.add(p2);
  21. ts.add(p3);
  22. for (Object i:ts ) {
  23. System.out.println(i);
  24. }
  25. }
  26. }
  27. //单独在这里写一个比较器
  28. //比较器实现java.util.Comparator接口
  29. class person{
  30. int age;
  31. public person(int age){
  32. this.age=age;
  33. }
  34. public String toString(){
  35. return "person[age="+age+"]";
  36. }
  37. }
  38. //比较器
  39. class PersonComparator implements Comparator<person>{
  40. @Override
  41. public int compare(person o1, person o2) {
  42. //按照年龄排序
  43. return o1.age-o2.age;
  44. }
  45. }

 运行结果:

  •   person[age=12]
      person[age=52]
      person[age=92]
      person[age=102]

Comparable接口和Comparator怎么选择呢?

  • 当比较规则不会发生改变的时候,或比较规则只有1个的时候,建议实现Comparable接口。

  • 如果比较规则有多个的时候,并且需要多个比较规则之间频繁切换,建议使用Comparator比较器。

Comparator的设计符合OCP原则。。

支持:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/766069
推荐阅读
相关标签