大厂Java初级开发工程师!!!面试必问项之Set实现类:TreeSet

一、TreeSet 概述

  • 1、TreeSetSortedSet 接口的实现类, TreeSet 可以确保集合元素处于排序状态。

  • 2、TreeSet顾名思义他内部维护的是一个TreeMap,底层是红黑二叉树,他使得集合内都是有序的序列。

  • 3、Tree可以按照添加对象的指定属性,进行排序,所以向TreeSet中添加的数据,要求是相同类的对象。

  • 4、两种排序方式:自然排序(实现Comparable接口) 和 定制排序(Comparator);

  • 5、自然排序中,比较两个对象是否相同的标准为:compareTo()返回0.不再是equals()

  • 6、定制排序中,比较两个对象是否相同的标准为:compare()返回0.不再是equals()

  • 7、对 TreeSet进行遍历的时候,默认是使用自然排序的规则来排序的;

  • 8、TreeSet 添加自定义类的对象时候,必须要有自然排序或定制排序,否则抛出异常:cannot cast to java.lang.Comparable;

二、TreeSet 结构

1、TreeSet 声明

1 public class TreeSet<E> extends AbstractSet<E>
2     implements NavigableSet<E>, Cloneable, java.io.Serializable

2、TreeSet 类继承结构

3、红黑树

TreeSet和后要的TreeMap采用红黑树的存储结构

特点:有序,查询速度比List快

三、TreeSet 创建

1、构造器

TreeSet是基于红黑树结构实现的,会对元素进行排序,TreeSet 提供了五种构造器:

public TreeSet() {this(new TreeMap<E,Object>());
}TreeSet(NavigableMap<E,Object> m) {this.m = m;
}
public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));
}
public TreeSet(Collection<? extends E> c) {this();addAll(c);
}
public TreeSet(SortedSet<E> s) {this(s.comparator());addAll(s);
}

里面的 m 属性是什么:


/*** The backing map.*/private transient NavigableMap<E,Object> m;// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT = new Object();//加入Java开发交流君样:593142328一起吹水聊天

可以看到里面是维护了一个 NavigableMap。

2、通过 Comparator 实例创建 TreeSet

上面的四个构造函数中着重要介绍第三个,它通过Comparator实例来创建TreeMap,那么Comparator到底是何方神圣呢?

通过阅读Comparator的源码发现,这是一个用于集合类排序的辅助接口,用户需要实现compare方法。

如果用户用了这种方式创建TreeSet,那么集合元素就不需要做额外处理,否则集合元素都需要实现Comparable接口,因为Tree在排序的时候会调用compare或者compareTo方法(介绍TreeMap的时候会具体讲解)。

下面来看看写的一个样例代码:


public class MyComparator implements Comparator<Person> {@Overridepublic int compare(Person o1, Person o2) {return o1.age - o2.age;}}
public class Person {public Integer age;public Person(Integer value) {this.age = value;}
}
public static void TreeSetTest() {// TreeMap在底层put元素的时候会判断是否存在Comparator实例,如果存在,则每次添加元素排序比较的时候会调用compare接口。TreeSet<Person> set = new TreeSet<Person>(new MyComparator());Person p1 = new Person(1);Person p2 = new Person(1);Person p3 = new Person(5);Person p4 = new Person(9);Person p5 = new Person(10);set.add(p1);set.add(p2);set.add(p3);set.add(p4);set.add(p5);Iterator<Person> i = set.iterator();while (i.hasNext()) {Person p = (Person) i.next();System.out.println(p.age);}
}
打印结果:
1
5
9
10

四、TreeSet 方法

五、NavigableSet接口介绍

常用方法:

// 返回比当前元素小的最近的一个元素
public E lower(E e) {return m.lowerKey(e);
}
// 返回小于等于当前元素的最近一个元素
public E floor(E e) {return m.floorKey(e);
}
// 返回大于等于当前元素的最近一个元素
public E ceiling(E e) {return m.ceilingKey(e);
}
// 返回大于当前元素的最近一个元素
public E higher(E e) {return m.higherKey(e);
}

六、TreeSet 与 比较器

1、自然排序

  • (1)自然排序:TreeSet会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。

  • (2)如果试图把一个对象添加到TreeSet时,则该对象的类必须实现 Comparable接口。
          实现Comparable 的类必须实现compareTo(Object obj)方法,两个对象即通过compareTo(Object obj)方法的返回值来比较大小。

  • (3)Comparable 的典型实现:
          ① BigDecimalBigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较;
          ② Character:按字符的 unicode值来进行比较;
          ③ Boolean:true 对应的包装类实例大于 false 对应的包装类实例;
          ④String:按字符串中字符的 unicode 值进行比较
          ⑤ DateTime:后边的时间、日期比前面的时间、日期大

  • (4)向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。

  • (5)因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象。

  • (6)对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj)方法比较返回值。

  • (7)当需要把一个对象放入 TreeSet中,重写该对象对应的 equals()方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过
    equals() 方法比较返回 true,则通过 compareTo(Object obj)方法比较应返回 0。否则,让人难以理解。

2、定制排序


(1)TreeSet的自然排序要求元素所属的类实现Comparable接口,如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。
    (2)利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2
    (3)要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。
    (4)此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。
    (5)使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。


七、案例

1、自定义类的自然排序

案例:

public class User implements Comparable{private String name;private int age;public User() {}public User(String name, int age) {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;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {System.out.println("User equals()....");if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;if (age != user.age) return false;return name != null ? name.equals(user.name) : user.name == null;}@Overridepublic int hashCode() { //return name.hashCode() + age;int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}//按照姓名从大到小排列,年龄从小到大排列@Overridepublic int compareTo(Object o) {if(o instanceof User){User user = (User)o;
//            return -this.name.compareTo(user.name);int compare = -this.name.compareTo(user.name);if(compare != 0){return compare;}else{return Integer.compare(this.age,user.age);}}else{throw new RuntimeException("输入的类型不匹配");}}
}

使用TreeSet保存:

@Testpublic void test1(){TreeSet set = new TreeSet();set.add(new User("Tom",12));set.add(new User("Jerry",32));set.add(new User("Jim",2));set.add(new User("Mike",65));set.add(new User("Jack",33));set.add(new User("Jack",56));Iterator iterator = set.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}

注意:如果在自然比较器中并没有对年龄进行比较,当姓名一样时,就会认为这两个对象一样,不会再次存放;

如果在比较器中对两个属性都进行了比较,当有一个属性不一样就会放入 TreeSet中。

可以发现,这里对两个对象的比较并不是使用 equals() 方法,而是使用比较器来进行比较的。

2、自定义类的定制排序

定制排序:

@Testpublic void test2(){Comparator com = new Comparator() {//按照年龄从小到大排列@Overridepublic int compare(Object o1, Object o2) {if(o1 instanceof User && o2 instanceof User){User u1 = (User)o1;User u2 = (User)o2;return Integer.compare(u1.getAge(),u2.getAge());}else{throw new RuntimeException("输入的数据类型不匹配");}}};TreeSet set = new TreeSet(com);  //按照给定的比较器进行排序set.add(new User("Tom",12));set.add(new User("Jerry",32));set.add(new User("Jim",2));set.add(new User("Mike",65));set.add(new User("Mary",33));set.add(new User("Jack",33));set.add(new User("Jack",56));Iterator iterator = set.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}

最后,祝大家早日学有所成,拿到满意offer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Android笔记】如何创建列表视图3

接着上一篇实现一个带有复选框的列表视图&#xff0c;这要求对Adapter有比较清楚的理解。1. ArrayAdapter从Layout读取TextView控件&#xff0c;返回给ListView显示&#xff0c;这个处理在ArrayAdapter的getView方法里&#xff0c;我们可以继承这个类&#xff0c;覆盖getView&…

史上最硬核的数学老师!搞发明、造大炮,让战斗民族直叫爸爸,看完我跪了......

全世界只有3.14 % 的人关注了爆炸吧知识一直以来&#xff0c;有好多朋友在后台和知识君吐槽&#xff0c;自己在追逐菲尔兹奖的路上总被数学公式所绊倒&#xff0c;一见到数学公式就头疼&#xff01;这时&#xff0c;知识君就会搬出数学史上最萌的公式——“么么哒”公式&#x…

a标签传参接收_[pyecharts1.8] 系列配置之标签设置

今日心情 &#xff1a;em....又是一堆蛋疼的事情堆积的一周...文章会迟到&#xff0c;但不会缺席&#xff0c;准备好脑子接收下[pyecharts1.8] 系列配置之标签设置本文档(以及pyecharts使用手册中的其他文档)将会持续更新。 有些内容标记为待更新的&#xff0c;有时间我会补充上…

这个寒冬,如何让我们的身价翻倍?

这个寒冬&#xff0c;如何让我们的身价翻倍&#xff1f; ——《深入理解.NET&#xff08;第2版英文版&#xff09;》读后感 微软4大名著评选结果揭晓 在开始正文之前&#xff0c;我先给大家讲一个真实的故事&#xff1a;我有一位朋友&#xff0c;他的一位同学原来是做测试的&am…

ASP.NET Core 配置 - 创建自定义配置提供程序

ASP.NET Core 配置 - 创建自定义配置提供程序在本文中&#xff0c;我们将创建一个自定义配置提供程序&#xff0c;从数据库读取我们的配置。我们已经了解了默认配置提供程序的工作方式&#xff0c;现在我们将实现我们自己的自定义配置提供程序。对于自定义配置提供程序&#xf…

为什么你的孩子拼命做题,成绩还总是上不去?

▲ 点击查看以前有句名言&#xff1a;“学好数理化&#xff0c;走遍天下都不怕。”这句话放到现在可能并不一定适用&#xff0c;但是数理化生仍然是在孩子整个学习生涯中&#xff0c;占比分量非常重的学科。然而&#xff0c;对很多孩子而言&#xff0c;学习数理化生却是很枯燥乏…

js请求结果拦截机器_CefSharp请求资源拦截及自定义处理

前言在CefSharp中&#xff0c;我们不仅可以使用Chromium浏览器内核&#xff0c;还可以通过Cef暴露出来的各种Handler来实现我们自己的资源请求处理。什么是资源请求呢&#xff1f;简单来说&#xff0c;就是前端页面在加载的过程中&#xff0c;请求的各种文本&#xff08;js、cs…

ListView

2019独角兽企业重金招聘Python工程师标准>>> ListView总结(多选框ListViiew,动态加载&#xff0c;多线程更新ListView中的进度条) convertView缓存及使用 ListView 更高效的使用 Adapter ListView中convertView和ViewHolder的工作原理 convertView&setTag方…

原来,程序的世界远比我想象的精彩

原来&#xff0c;程序的世界远比我想象的精彩 注&#xff1a;本文转载自http://www.cnblogs.com/dingxue/archive/2008/12/23/1360908.html&#xff0c;作者丁学。文中所有的 Pxx 指得是《Erlang程序设计》一书中的页码&#xff0c;书的信息放在文章最后。人都说无知者无畏&am…

【MSLearn 学习模块】Hi ! ⼀起来学Python

随着大数据、人工智能、物联网的兴起&#xff0c;Python越来越受到大家的关注。不论你是⼀位学生&#xff0c;是一位传统的码农&#xff0c;还是非计算机领域的从业人员都离不开Python。当然大家的角度不⼀样&#xff0c;作为学生是以学为主&#xff0c;码农是以用为主&#xf…

有趣的12张数学原理动图,令人舒心却又伤脑!你看懂几个?

全世界只有3.14 % 的人关注了爆炸吧知识下面的12张数学动图你能看懂几个&#xff0c;反正知识君是都看懂了。1.被简单证明的勾股定理给三角形加上一点厚度。从面积问题&#xff0c;跳转到了具象的体积问题。2.勾股定理的面积证明法Its a long story……慢慢看。3.周长和直径的π…

typora插入代码设置_Typora基本功能介绍

Typora是什么&#xff1f;提起Typora&#xff0c;如果是使用过Markdown的人&#xff0c;应该就不太陌生&#xff0c;Typora 是一款支持实时预览的 Markdown 文本编辑器。它有 OS X、Windows、Linux 三个平台的版本&#xff0c;并且由于仍在测试中&#xff0c;是完全免费的。在T…

【DotNetMLLearn】.NET Core人工智能系列-概述

.NETer大家好&#xff0c;今天为大家送上.NET Core 下如何完成人工智能应用的系列&#xff0c;希望给.NETer进入人工智能领域提供一个指引。.NET Core已经是一个全场景应用的技术栈方案&#xff0c;对于每一个领域都有支持。自从微软在开源发力后&#xff0c;.NET Core的社区能…

fanuc机器人控制柜接线_FANUC涂胶标定参考

FANUC涂胶标定参考1、进入SETUP界面2、选择DISPENCE界面3、选择15 flow rate control,按F2 detail进入4、进入标定界面此画面定义含义如下&#xff1a;(1)为涂胶标定单位,TCPP BEAD WIDTH宽度为基准(2)为 输入理想涂胶宽度,desired flow rate(3)为定义出胶轨迹sample program(一…

硬盘坏道修复白皮书

常识&#xff1a;硬盘坏道分类 - 不同坏道分仔细由于硬盘采用磁介质来存储数据&#xff0c;在经历长时间的使用或者使用不当之后&#xff0c;难免会发生一些问题&#xff0c;也就是我们通常所说的产生“坏道”&#xff0c;当然这种坏道有可能 是软件的错误&#xff0c;也有可能…

糟糕!复工后,最让人担心的问题又又又来了!

▲ 点击查看你复工多久了&#xff1f;当我们在家宅着的时候&#xff0c;一天到晚都想着什么时候才能出去。然而现在公司一通知复工&#xff0c;其实心里还是有点犯怵。先不说通勤了&#xff0c;上班吃饭就有又成为大家绕不开的问题。现在虽然可以在外面点外卖&#xff0c;但说实…

Myeclipse中Tomcat的两种部署方式

一、在Myeclipse软件中部署 1、 在Myeclipse中&#xff0c;创建好工程后&#xff0c;在Myeclipse菜单栏中选择 Windows -> Preferences -> Myeclipse -> Tomcat5&#xff0c;选择"Enable"&#xff1b;Tomact Home Directory要选择你机器上Tomcat所安装的目录…

配置yml_dctc:生成docker-compose.yml配置的工具

有时候&#xff0c;我们需要想知道docker容器的运行参数、环境变量等配置&#xff0c;以便容器以后被删掉之后&#xff0c;可以重新运行起来。特别是在测试环境&#xff0c;有些容器可能就是一个docker run就运行起来了。或者随便找一个目录丢了一个docker-compose.yml运行起来…

Silverlight 2 应用程序部署到任意HTML页面

Silverlight 2 应用程序部署到任意HTML页面&#xff0c;可以采用ActiveX的方法&#xff0c;在页面中放入object标签&#xff0c;设置相应的属性即可。使用 object 元素&#xff0c;可以用与所有受支持浏览器兼容的方式在 HTML 中嵌入和配置 Silverlight 插件。具体可参看&#…

对于“知识”,我们存在哪些误解?

全世界只有3.14 % 的人关注了爆炸吧知识对于不少用户来说&#xff0c;微信已经成为了获取新资讯的重要途径之一。如何保证自己找到「值得看」的内容&#xff1f;每天更新的文章这么多&#xff0c;哪些才值得你看呢&#xff1f;今天就为大家推荐一些颜值与才华并存的好评公众号。…