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 Map
private 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 {
// 创建一个新的HashSet
HashSet<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);
// 输出修改后的HashSet
System.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]
总结
- HashSet、LinkedHashSet 和 TreeSet 都是 Set 接口的实现类,都能保证元素唯一,并且都不是线程安全的。
- HashSet、LinkedHashSet 和 TreeSet 的主要区别在于底层数据结构不同。HashSet 的底层数据结构是哈希表(基于 HashMap 实现)。LinkedHashSet 的底层数据结构是链表和哈希表,元素的插入和取出顺序满足 FIFO。TreeSet 底层数据结构是红黑树,元素是有序的,排序的方式有自然排序和定制排序。
- 底层数据结构不同又导致这三者的应用场景不同。HashSet 用于不需要保证元素插入和取出顺序的场景,LinkedHashSet 用于保证元素的插入和取出顺序满足 FIFO 的场景,TreeSet 用于支持对元素自定义排序规则的场景。
- 此外,HashSet、LinkedHashSet允许有 null 值,TreeSet不允许有null值,当向 TreeSet 插入 null 元素时,TreeSet 使用 compareTo 方法与 null 元素进行比较,报错:java.lang.NullPointerException。
结尾彩蛋
如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?的更多相关文章
- [每日一题]面试官问:for in和for of 的区别和原理?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- Java提高篇(三五)-----Java集合细节(一):请为集合指定初始容量
集合是我们在Java编程中使用非常广泛的,它就像大海,海纳百川,像万能容器,盛装万物,而且这个大海,万能容器还可以无限变大(如果条件允许).当这个海.容器的量变得非常大的时候,它的初始容量就会显得很重 ...
- 学完了这篇JVM,面试官真拿我没办法了!
在我们面试中经常会遇到面试官问一些有关JVM的问题,下面我大概从运行时数据域.类加载机制.类加载器.垃圾收集器.垃圾收集算法.JVM堆内存模型.JVM内存结构.JVM调优等几个方面来讲一下JVM. 一 ...
- 超详细的Java面试题总结(三)之Java集合篇常见问题
List,Set,Map三者的区别及总结 List:对付顺序的好帮手 List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象 Set:注重独一无二的性质 不允许重复的集合.不会有多个元 ...
- 100道Java高频面试题(阿里面试官整理)
我分享文章的时候,有个读者回复说他去年就关注了我的微信公众号,打算看完我的所有文章,然后去面试,结果我后来很长时间不更新了...所以为了弥补一直等我的娃儿们,给大家的金三银四准备了100道花时间准备的 ...
- Java集合总结—再也不怕面试问到集合了
Java集合总结 1.常见的集合 Map接口和Collection接口是所有集合框架的父接口: Collection接口的子接口包括:Set接口和List接口 Map接口的实现类主要有:HashMap ...
- 不可错过的java面试博客之java集合篇
1. List List 是有序的 Collection.Java List 一共三个实现类: 分别是 ArrayList.Vector 和 LinkedList ArrayList ArrayLis ...
- Java集合篇六:Map中key值不可重复的测试
package com.test.collection; import java.util.HashMap; import java.util.Map; //Map中key值不可重复的测试 publi ...
- Java集合篇五:HashMap
1.HasMap 自定义基础版 package com.test.collection; /** * 自定义实现Map功能 * map :存放键值对,根据键对象找对应的值对象 * @author ch ...
- Java集合篇四:Map的基本应用
package com.test.collection; import java.util.HashMap; import java.util.Hashtable; import java.util. ...
随机推荐
- DEV-C++调试报错
1.报错信息如下: 2.原因 SIGSEGV是是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号. 意思是程序接受一个无效的指针地址,Segmentation fault即是提示我们去 ...
- [转帖]从小白到精通:揭秘perf工具的全部功能与操作技巧
https://zhuanlan.zhihu.com/p/664396453 目录 收起 一.引言 二.理解perf工具的基本概念 三.安装与配置perf工具 3.1.不同操作系统的perf工具安 ...
- [转帖]MySQL数据类型(decimal的存储大小)
本来还以为MySQL的数据类型挺简单的,没想到竟然有很多坑,容我仔细道来 MySQL数据类型 整数类型(注意是字节) 浮点型(重点关注decimal) 字符型(注意这是4.x版本的定义,5.x以后已经 ...
- [转帖]从SSTable到LSM-Tree之二
https://zhuanlan.zhihu.com/p/103968892 背景 LSM-Tree (Log Structured Merge Tree),日志结构合并树.它在 1996 年由论文& ...
- Nginx arm编译安装
Nginx arm编译安装 背景 计划编译一套产品. 能够比较方便快捷的进行 nginx的交付. 主要思想是源码编译 不仅能够在arm上面运行 也可以在x86上面编译 考虑性能还有一些扩展性. 高效处 ...
- 【转帖】Linux开发工具 — readelf、objdump、hexdump
本博文的主要内容是:1)readelf工具查看ELF文件的信息:2)hexdump工具查看这块内存:3)objdump工具对文件进行反汇编. 前一段时间对Linux不熟,所以很多命令不知道.学习C时候 ...
- [转帖]Linux下strace调试系统应用参数总结(附实例操作讲解)
文章目录 一.简介 二.常用参数详解 三.实例详解 3.1 跟踪具体进程 3.2 监控具体程序执行过程 四.其他相关知识链接 一.简介 strace命令是一个集诊断.调试.统计与一体的Linux 用户 ...
- vue中$children的理解
官网介绍 $children $children 获取当前实例的直接子组件 .需要注意 $children 并不保证顺序,也不是响应式的.[特别重要] 如果你发现自己正在尝试使用 $children ...
- git查看自己是从那个分支建的分支
可能发生的情况 很多时候,开始建分支的时候, 能够确认自己是那个分支建的,但是当写完功能之后, 再去回想,有时是忘记自己基于那个分支建的分支. 这时有一个命令的话就可以很快的定位了. 查看创建的分支来 ...
- 【JS 逆向百例】webpack 改写实战,G 某游戏 RSA 加密
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...