Java HashSet和TreeSet【笔记】
Java HashSet和TreeSet【笔记】
PS:HashSet、TreeSet 两个类是在 Map 的基础上组装起来的类
HashSet
类注释
1.底层实现基于 HashMap,所以迭代时不能保证按照插入顺序,或者其它顺序进行迭代
2.add、remove、contanins、size 等方法的耗时性能,是不会随着数据量的增加而增加的,这个主要跟 HashMap 底层的数组数据结构有关,不管数据量多大,不考虑 hash 冲突的情况下,时间复杂度都是 O (1)
3.线程不安全的,如果需要安全请自行加锁,或者使用 Collections.synchronizedSet
4.迭代过程中,如果数据结构被改变,会快速失败的,会抛出 ConcurrentModificationException 异常
HashSet结构
HashSet使用的就是组合 HashMap,组合就是把 HashMap 当作自己的一个局部变量
在 Java 中,要想基于基础类进行创新实现的话,有两种办法:
第一种是继承基础类,覆写基础类的方法,比如说继承 HashMap , 覆写其 add 的方法
第二种是组合基础类,通过调用基础类的方法,来复用基础类的能力
其优点如下:
1.继承表示父子类是同一个事物,而 Set 和 Map 本来就是想表达两种事物,所以继承不妥,而且 Java 语法限制,子类只能继承一个父类,后续难以扩展
2.组合更加灵活,可以任意的组合现有的基础类,并且可以在基础类方法的基础上进行扩展、编排等,而且方法命名可以任意命名,无需和基础类的方法名称保持一致
HashSet 初始化
HashSet 的初始化直接 new HashMap 即可,有意思的是,在有原始数据进行初始化的情况下,会对 HashMap 的初始容量进行计算(取括号中两个数的最大值,Math.max((int) (c.size()/.75f) + 1, 16))
源码:
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
可以看出两方面的事情
第一,和 16 比较大小的意思是说,如果给定 HashMap 初始容量小于 16 ,就按照 HashMap 默认的 16 初始化好了,如果大于 16,就按照给定值初始化
第二,HashMap 扩容的伐值的计算公式是:Map 的容量 * 0.75f,一旦达到阀值就会扩容,此处用 (int) (c.size ()/.75f) + 1 来表示初始化的值,这样使我们期望的大小值正好比扩容的阀值还大 1,就不会扩容,符合 HashMap 扩容的公式
HashSet 其他方法
其他方法就是对 Map 的 api 进行了一些包装,如下的 add 方法实现,直接使用 HashMap 的 put 方法,进行一些简单的逻辑判断
代码:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
从 add 方法中,我们就可以看到组合的好处,方法的入参、名称、返回值都可以自定义,如果是继承的话就不能自定义了
HashSet值得参考的地方
1.对组合和继承的分析和把握
2.对复杂逻辑的包装,要让放出去的接口尽量简单好用
3.尽量多对组合的 api 多些了解,这样在组合其他 api 时,才能更好的使用 api
TreeSet
TreeSet基本结构
TreeSet 的结构和 HashSet 相似,底层组合的是 TreeMap,所以其继承了 TreeMap key 能够排序的功能,在迭代的时候,也可以按照 key 的排序顺序进行迭代
TreeSet 组合 TreeMap 实现的思路
TreeSet 组合 TreeMap 实现的思路有两种
第一种,TreeSet 直接使用 TreeMap 的某些功能,自己包装成新的 api(add方法),适合用于简单的场景
add方法源码:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
第二种,TreeSet 定义自己想要的 api,自己定义接口规范,让 TreeMap 去实现(NavigableSet 接口),也就是说,TreeSet 把接口定义出来后,让 TreeMap 去实现内部逻辑,TreeSet 负责接口定义,TreeMap 负责具体实现,适合用于复杂的场景,这种思想比较重要,很多都是这种复用思想
NavigableSet 接口源码:
public interface NavigableSet<E> extends SortedSet<E> {
Iterator<E> iterator();
E lower(E e);
}
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
比较重要的就是HashSet 小结以及TreeSet 两种复用思路

Java HashSet和TreeSet【笔记】的更多相关文章
- Java——HashSet和TreeSet的区别
HashSetHashSet有以下特点 不能保证元素的排列顺序,顺序有可能发生变化 不是同步的 集合元素可以是null,但只能放入一个null当向HashSet集合中存入一个元素时,HashSe ...
- Java开发笔记(六十五)集合:HashSet和TreeSet
对于相同类型的一组数据,虽然Java已经提供了数组加以表达,但是数组的结构实在太简单了,第一它无法直接添加新元素,第二它只能按照线性排列,故而数组用于基本的操作倒还凑合,若要用于复杂的处理就无法胜任了 ...
- java集合系列——Set之HashSet和TreeSet介绍(十)
一.Set的简介 Set是一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素.对 e1 和 e2,并且最多包含一个为 null 的元素. S ...
- Java集合详解7:HashSet,TreeSet与LinkedHashSet
今天我们来探索一下HashSet,TreeSet与LinkedHashSet的基本原理与源码实现,由于这三个set都是基于之前文章的三个map进行实现的,所以推荐大家先看一下前面有关map的文章,结合 ...
- 【java提高】---HashSet 与TreeSet和LinkedHashSet的区别
HashSet 与TreeSet和LinkedHashSet的区别 今天项目开发,需要通过两个条件去查询数据库数据,同时只要满足一个条件就可以取出这个对象.所以通过取出的数据肯定会有重复,所以要去掉重 ...
- Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 上一篇总结了下ArrayList .LinkedList和Vector比较,今天泥瓦匠总结下Hash ...
- Java容器深入浅出之HashSet、TreeSet和EnumSet
Java集合中的Set接口,定义的是一类无顺序的.不可重复的对象集合.如果尝试添加相同的元素,add()方法会返回false,同时添加失败.Set接口包括3个主要的实现类:HashSet.TreeSe ...
- 30、Java中Set集合之HashSet、TreeSet和EnumSet
Set集合是Collection的子集,Set集合与Collection基本相同,没有提供任何额外的方法,只是Set不允许包含重复的元素. Set集合3个实现类:HashSet.TreeSet.Enu ...
- Java集合详解7:一文搞清楚HashSet,TreeSet与LinkedHashSet的异同
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
随机推荐
- SonarQube插件
关于插件我本身使用不多,如果看不惯英文界面,那么就先装个中文插件吧. 或者上微软的官方网站进行下载 将下载的插件上传到自己的sonarqube的服务的机器上,放置插件目录下,重启sonarqube即可 ...
- Flask(5)- 动态路由
前言 前面几篇文章讲的路由路径(rule)都是固定的,就是一个路径和一个视图函数绑定,当访问这条路径时会触发相应的处理函数 这样无法处理复杂的情况,比如常见的一个课程分类下有很多个课程,那么他们的 p ...
- 深入理解 PHP7 中全新的 zval 容器和引用计数机制
深入理解 PHP7 中全新的 zval 容器和引用计数机制 最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷惑. 仔细一想不难发现问题所 ...
- 扩大UIPageViewController的点击范围
UIPageViewController中的边缘点击手势大概是屏幕的1/6,市面的大多数阅读器点击手势都在1/3以上,或者我干脆想自定义点击的范围,但又不想放弃系统的翻页效果,这时候该怎么做了?其实很 ...
- nginx+waf防火墙
1.官网下载nginx源码包(nginx-1.20.0.tar.gz) 新建nginx安装目录mkdir -p /opt/nginx新增nginx运行用户useradd -s /sbin/nol ...
- ESCMScript6(3)Promise对象
1. Promise的含义 Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了P ...
- centos7下安装、配置Nginx、设置Nginx开机自启动
测试环境: [root@centos-linux ~]# cat /etc/redhat-releaseCentOS Linux release 7.6.1810 (Core) [root@cento ...
- CentOS下 Django部署 uWSGI+Django(一)
由于新冠疫情的缘故,公司要求员工停薪休假,赋闲在家的时候还是决定做点正事,学学习. 本人Linux入门水平,Python入门水平,所以在网上找的那些python部署的帖子,看的是云里雾里的,也没有达到 ...
- c#链接MySql数据库方法
方法一: 打开visual studio,在项目->管理NuGet程序包->搜索"MySql.Data"并安装: 在程序部分,引入 using MySql.Data.M ...
- 记一次 .NET 某云采购平台API 挂死分析
一:背景 1. 讲故事 大概有两个月没写博客了,关注我的朋友应该知道我最近都把精力花在了星球,这两个月时间也陆陆续续的有朋友求助如何分析dump,有些朋友太客气了,给了大大的红包,哈哈,手里面也攒了1 ...