Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?

写在开头

Java的集合世界中主要由List,Set,Queue,Map构成,我们在之前的博文中已经学习了List,接下来我们继续学习Set集合。
Set特点:存取无序,不可以存放重复的元素,不可以用下标对元素进行操作
在这里插入图片描述

HashSet

作为Set容器的代表子类,HashSet经常被用到,我们通过源码去分析它

【源码查看】

public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, java.io.Serializable
{private transient HashMap<E,Object> map;// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT = new Object();public HashSet() {map = new HashMap<>();}public boolean add(E e) {return map.put(e, PRESENT)==null;}public boolean remove(Object o) {return map.remove(o)==PRESENT;}
}

虽然HashSet实现了Set接口,但通过源码我们能够看到,它的底层逻辑实现其实依据的是HashMap,通过操作map的key值来实现元素的增删改查,下面通过一个小测试类去用下HashSet。

【代码示例1】

public class Test {public static void main(String[] args) throws FileNotFoundException {// 创建一个新的HashSetHashSet<Integer> set = new HashSet<>();// 添加元素set.add(3);set.add(4);set.add(0);set.add(1);set.add(4);// 输出HashSet的元素个数System.out.println("HashSet size: " + set.size());// 判断元素是否存在于HashSet中boolean containsWanger = set.contains(2);System.out.println(containsWanger);// 删除元素boolean removeWanger = set.remove(1);System.out.println(set);// 修改元素,需要先删除后添加boolean removeChenmo = set.remove(3);boolean addBuChenmo = set.add(4);System.out.println(removeChenmo && addBuChenmo);// 输出修改后的HashSetSystem.out.println(set);}
}

输出:

HashSet size: 4
false
[0, 3, 4]
false
[0, 4]

由代码结果进一步证明了我们的结论:
1、存储数据不重复,但add重复数据并不报错,原因是第一个数据会被第二次重复数据覆盖掉;
2,无序,很多人发现输出了一个有序的数字集合,这个其实与我们所说的有序是有区别的,在Set中的有序无序是指输入的顺序与输出的顺序是否一致 当然,想要实现有序可以通过LinkedHashSet,底层通过链表记录元素插入顺序。

面试考点
这里面其实包含着一个小小的Java面试考点,曾经有面试官问过这样的一个问题:

集合中的无序性和不可能重复性的什么意思?

  • 无序性:所谓无序性不等于随机性,也不等于输出无序,就如同上面我们看到的向HashSet中随机添加数字,输出是从大到小,看似有序,实际此序非彼序!真正的无序性是指存储的数据在底层数组中并非按照数组索引的顺序添加 ,而是根据数据的哈希值进行判断。
  • 不可重复性:指添加的元素按照 equals() 判断时 ,返回 false,因此,实现不可重复性,必须要同时重写 equals() 方法和 hashCode() 方法。

LinkedHashSet

那么有的小伙伴会问了:“我就想存一个不重复的数据集合,同时又想要他们有序怎么办呢?”,Java的开发人员已经早就为你想到了,这个办法就是用LinkedHashSet
LinkedHashSet 是基于 LinkedHashMap 实现的,并且使用链表维护了元素的插入顺序,具有快速查找、插入和删除操作的优点,又可以维护元素的插入顺序!源码就不带大家看了,咱们直接上测试案例。

【代码示例2】

LinkedHashSet<String> set = new LinkedHashSet<>();
// 添加元素
set.add("Hello");
set.add("Java");
set.add("Build");
set.add("Java");
System.out.println(set);
// 删除元素
set.remove("Hello");// 修改元素
set.remove("Java");
set.add("java");// 查找元素
boolean bool = set.contains("Build");
System.out.println("Build哥:" + bool);//输出
System.out.println(set);

输出:

[Hello, Java, Build]
Build:true
[Build, java]

通过输出结果我们可以得出结论:LinkedHashSet中的元素不可重复,有序。

TreeSet

通过上面两个集合类我们大概能够猜到,几乎所有的Set集合的底层都是通过Map去实现,TreeSet同样是基于TreeMap实现,TreeMap 基于红黑树实现,所以TreeSet也就自带了排序功能。

 public TreeSet() {this(new TreeMap<E,Object>());}

【代码示例3】

public class Test {public static void main(String[] args) {// 创建一个 TreeSet 对象TreeSet<Integer> set = new TreeSet<>();set.add(3);set.add(6);set.add(2);set.add(1);set.add(0);set.add(9);System.out.println(set);}
}

输出:

[0, 1, 2, 3, 6, 9]

总结

  1. HashSet、LinkedHashSet 和 TreeSet 都是 Set 接口的实现类,都能保证元素唯一,并且都不是线程安全的。
  2. HashSet、LinkedHashSet 和 TreeSet 的主要区别在于底层数据结构不同。HashSet 的底层数据结构是哈希表(基于 HashMap 实现)。LinkedHashSet 的底层数据结构是链表和哈希表,元素的插入和取出顺序满足 FIFO。TreeSet 底层数据结构是红黑树,元素是有序的,排序的方式有自然排序和定制排序。
  3. 底层数据结构不同又导致这三者的应用场景不同。HashSet 用于不需要保证元素插入和取出顺序的场景,LinkedHashSet 用于保证元素的插入和取出顺序满足 FIFO 的场景,TreeSet 用于支持对元素自定义排序规则的场景。
  4. 此外,HashSet、LinkedHashSet允许有 null 值,TreeSet不允许有null值,当向 TreeSet 插入 null 元素时,TreeSet 使用 compareTo 方法与 null 元素进行比较,报错:java.lang.NullPointerException。

结尾彩蛋

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

在这里插入图片描述

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

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

相关文章

Sentinel注解@SentinelResource详解

Sentinel注解SentinelResource详解 熔断 针对访问超过限制【sentinel中配置的限制】的资源&#xff0c;通过java代码配置&#xff0c;返回一个自定义的结果&#xff0c;需要用到 SentinelResource 注解的 blockHandlerClass 和 blockHandler 属性。 blockHandlerClass&#…

Electron实战之进程间通信

进程间通信&#xff08;IPC&#xff09;并非仅限于 Electron&#xff0c;而是源自甚至早于 Unix 诞生的概念。尽管“进程间通信”这个术语的确创造于何时并不清楚&#xff0c;但将数据传递给另一个程序或进程的理念可以追溯至 1964 年&#xff0c;当时 Douglas McIlroy 在 Unix…

review 10

整理磁盘操作的完整流程&#xff0c;如何接入虚拟机&#xff0c;是否成功识别&#xff0c;对磁盘分区工具的使用&#xff0c;格式化&#xff0c;挂载以及取消挂载、复习cp、mv和find指令 1&#xff1a;U盘接入虚拟机 在弹出窗口直接选择 虚拟机-可移动设备-找到u盘-连接 2&a…

04_device_bus_driverLinux内核模块

01_basicLinux内核模块-CSDN博客文章浏览阅读45次。环境IDubuntuMakefilemodules:clean:basic.creturn 0;运行效果。https://blog.csdn.net/m0_37132481/article/details/136157384?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%…

实习日志15

1.大改了一下界面 1.1.识别与验真 1.2.历史记录 2.改了几个bug 2.1.改json格式用JSON.stringify(value,null,2); 2.2.内嵌页面值与原页面值重复 2.3.验真条件判断 if (isVerifyCell.getValue() "不需要") {if (verifyResultCell.getValue() ! "未查验")…

树和二叉树的基本知识

一、树的概念及结构 1.树的概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 。 有一个 特殊…

分享一个学英语的网站

名字叫&#xff1a;公益大米网​​​​​​​ Freerice 这个网站是以做题的形式来记忆单词&#xff0c;题干是一个单词&#xff0c;给出4个选项&#xff0c;需要选出其中最接近题干单词的选项。 答对可以获得10粒大米&#xff0c;网站的创办者负责捐赠。如图 触发某些条件&a…

Linux系统的历史记录添加时间和IP信息

1 为什么要优化系统历史记录 对于linux系统&#xff0c;默认情况下&#xff0c;系统记录的历史命令比较简单。某些历史记录可能也无法正常保存&#xff0c;因此当服务器出现异常&#xff0c;希望通过历史命令来了解曾经做了哪些操作时&#xff0c;往往非常被动&#xff0c;下面…

挑战杯 基于CNN实现谣言检测 - python 深度学习 机器学习

文章目录 1 前言1.1 背景 2 数据集3 实现过程4 CNN网络实现5 模型训练部分6 模型评估7 预测结果8 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于CNN实现谣言检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&am…

宜昌博物馆龙文物展,以数据为盾完成文物保护

​一、湖北宜昌博物馆龙文物精品展的独特魅力 近日&#xff0c;在湖北宜昌博物馆举行的甲辰年龙文物精品展上&#xff0c;多件包含“龙元素”的文物正式向社会展出。龙自古以来就是中华民族象征&#xff0c;带有“龙图案”或“龙元素”的物件&#xff0c;广泛存在于中国人“吃…

vue-productionSourceMap作用

当其设置为false时(productionSourceMap: false) 当其设置为true时(productionSourceMap: true) 注:1.当设置为true时,打包后每个文件都有一个.map文件,其目的是为了精确定位代码错误 2.当设置为false时,可减少项目打包大小 3.正式环境禁止使用true,因为其可通过反编译.map文件…

固定资产与总账对账,业务系统出不来数据?

1、【财务会计】-【固定资产】-【与总账对账】 2、【财务会计】-【总账】-【对账执行】 以上两个节点都可以进行 “固定资产与总账” 对账执行 操作。 问题: 固定资产与总账对账,业务系统出不来数据?如下图 : 原因: 固定资产对账要确保,对账月是最早对账月才行,即…