【JAVA】LinkedHashSet集合的概念及其与LinkedHashMap有序的原因
LinkedHashSet集合特点
LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。并且linkedHashSet是一个非线程安全的集合。如果有多个线程同时访问当前linkedhashset集合容器,并且有一个线程对当前容器中的元素做了修改,那么必须要在外部实现同步保证数据的冥等性。
冥等性的理解:http://www.smithfox.com/?e=16
LinkedHashSet集合的源码实现
我们new一个LinkedHashSet看一下具体的源码实现。
LinkedHashSet<List> l = new LinkedHashSet<>();
注:这里我们实际创建的是一个LinkedHashMap带有制定大小和加载因子的容器。
深入理解java中的容器:https://blog.csdn.net/a2011480169/article/details/52047600
/**
* ...
*/
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
/**
* ...
*/
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
/**
* ...
*/
public LinkedHashSet() {
super(16, .75f, true);
}
/**
* ...
*/
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
LinkedHashSet集合的实质
LinkedHashSet实际上是一个哈希表和链表的结合,且是一个双向链表。
双向链表是链表的一种,他的每个数据节点都有两个指针分别指向直接后继和直接前驱,所以从双向链表的任意一个节点开始都可以很方便的访问它的前驱节点和后继节点。这是双向链表的优点,那么有优点就有缺点,缺点是每个节点都需要保存当前节点的next和prev两个属性,这样才能保证优点。所以需要更多的内存开销,并且删除和添加也会比较费时间。
插入顺序的保证
那是LinkedHashSet集合是如何保证数据插入顺序的?
java单向和双向链表详解:https://blog.csdn.net/Sun_Ru/article/details/51784058
在新创建的LinkedHashSet的对象的下面,对元素进行添加。我们走进去看一下add();方法
跟进来走的是put的方法:LinkedHashSet.class下的,这个是重写了父类(超类)中put的具体add方法。他会在新分配的元素在链表的末尾插入一条。
进来走的还是HashMap的put添加方法,在上面的判断和计算hash确定位置之后,由于LinkedHashSet重写了addEntry
在元素的后面添加新的元素。
整个过程就是LinkedHashSet在容器插入数据的过程。此过程主要由LinkedHashSet.class中重写超类的两个addEntry和createEntry 实现双向链表的结构。保证数据已我们录入的顺序遍历输出。
注:IntelliJ IDEA中 查看某个类中的所有方法的组合键:
https://blog.csdn.net/tb9125256/article/details/81416358
https://blog.csdn.net/qq_27093465/article/details/50853429
LinkedHashSet集合与LinkedHashMap有序的原因
哈希表是无序的 因为往进去存的元素都是随机存的。而它之所以有序的原因是,往里头存的元素多了一个指针。 我们一般往哈希表里存的是KeyValue,而只要带哈希的,我们往里头存的,就有KeyValue和next的指针。 所以,我们存的时候随便存,但是指针是按顺序把每个元素连起来的。 比如说,我们可以将元素存到数组里头,而他的地址我们可以通过next指针,用链表按顺序将其连起来。 也就是说,在数组里我们随便存元素的值。可是该元素的地址,我们将其存给第一个元素。 在迭代的时候其实就是用链表在迭代,即存的时候用哈希存,因为速度快。访问的时候用链表访问,为的是有序。
相关文章
- java实现第三届蓝桥杯拼音字母
- Java实现 蓝桥杯 基础练习 杨辉三角形
- (Java实现) 活动选择
- 【JAVA】java中split以"." 、""、“|”分隔字符串
- 【JAVA】 02-Java对象细节
- [Linux] Install java and add JAVA_HOME, PATH
- Java bean 是个什么概念?
- Java内存模型一个经典例子-指令重排序与CPU指令多发射导致执行结果异常
- [Spring学习笔记 4 ] AOP 概念原理以及java动态代理
- Java反射机制详解
- Java SSM篇5——SpringMVC
- 使用Java标准的java.util.EventListener实现观察者-发布者设计模式
- java 队列总结queue v3 svv.docxjava 队列总结queue v3 svv.docx atitit. java queue 队列体系总结o7t 1. 队列概念1 1.1. 队列
- Atitit.导出excel报表的设计与实现java .net php 总
- How to improve Java's I/O performance( 提升 java i/o 性能)
- 【java】Java经典面试题整理(附答案)
- 【java】Java ArrayList
- Java并发编程核心概念一览
- Java如何将每个单词的第一个字符转为大写?
- JAVA的核心概念:接口(interface)
- Java国际化概念和使用介绍
- 【java】Java 封装
- 【java】Java并发编程--Java实现多线程的4种方式