JAVA的那些数据结构实现总结,实现,扩容说明
能沉淀下来的东西,往往都很基础,整理了下JAVA中遇到的数据结构
目录大纲:
到目前接触到的
有几个说明:
可扩容数组
ArrayList 扩容数组的实现, 满了后扩容,扩容在1.5倍,通过copy过来,无扩容因子
int newCapacity = oldCapacity + (oldCapacity >> 1);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
可扩容的数组链表
数组链表的扩容实现:
以HashMap为例子, 当链表深度过长,或生产个新的数组链表进行copy
注意:
扩容过程中容易出现死链,下面是死链的个演示:
扩容前
[ 1 ] [ 2 ] [ 3 ] [ 空]
5 10
第一个线程扩容后,数组链表如下
[ 1 ] [ 10 ] [3] [] [] [] []
2
第二个线程又把从头把2指向10,然后2和10形成了个死循环
扩容代码
//对HashMap死链理解的注解 . 2017.02.17 by 何锦彬 JDK,1.7.51 void transfer(Entry[] newTable, boolean rehash) {
//获取新table的容量
int newCapacity = newTable.length;
//迭代以前的数组
for (Entry<K,V> e : table) {
//如果数组上有元素
while(null != e) {
// 赋值next
Entry<K,V> next = e.next;
//获取e在新的table里的位置
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
//把e指向当前的新数组里的第一个元素,这里会并发了,如果在这断点等待下个线程过来,就会死循环,尝试下
e.next = newTable[i];
//替代新数组的位置
newTable[i] = e;
e = next;
}
}
}
栈
stack栈的实现 ,基于数组继承自Vector(故线程安全):
获取peek():get(len-1)
出栈 pop(): 从数组最大坐标开始取出,peek(len-1) , 然后remove
入栈 push(o) : add(o)
阻塞队列
阻塞队列的实现:
基于数组和单向链表
获取:peek(),
实现:重入锁保证线程安全,peek(),从顶部获取
阻塞入队:put(o),
实现: 重入锁保证线程安全,通过Condition阻塞,无超时,支持Interrupt
带超时阻塞入队: offer(o,timeout, tmeUnit),
实现: 重入锁保证线程安全,通过Condition阻塞,condition方法,awaitNanos(纳秒),支持Interrupt
其它注意点:
当前数组的大小: AtomicInteger计算,用CAS保证同步,记得ReentrantLock必须是全局变量,局部的话,每次锁的对象是this.
红黑树:
红黑树的实现,TreeMap举例,加入自己的注释的理解:
//对treeMap的红黑树理解注解. 2017.02.16 by 何锦彬 JDK,1.7.51<br> <br>/** From CLR */
private void fixAfterInsertion(Entry<K, V> x) { //新加入红黑树的默认节点就是红色
x.color = RED;
/**
* 1. 如为根节点直接跳出
*/
while (x != null && x != root && x.parent.color == RED) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { //如果X的父节点(P)是其父节点的父节点(G)的左节点
//即 下面这种情况
/**
* G
* P(RED) U
*/
//获取其叔(U)节点
Entry<K, V> y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
// 这种情况,对应下面 图:情况一
/**
* G
* P(RED) U(RED)
* X
*/
//如果叔节点是红色的(父节点有判断是红色). 即是双红色,比较好办,通过改变颜色就行. 把P和U都设置成黑色然后,X加到P节点。 G节点当作新加入节点继续迭代
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
//处理红父,黑叔的情况
if (x == rightOf(parentOf(x))) {
// 这种情况,对应下面 图:情况二
/**
* G
* P(RED) U(BLACK)
* X
*/
//如果X是右边节点
x = parentOf(x);
// 进行左旋
rotateLeft(x);
}
//左旋后,是这种情况了,对应下面 图:情况三
/**
* G
* P(RED) U(BLACK)
* X
*/ // 到这,X只能是左节点了,而且P是红色,U是黑色的情况
//把P改成黑色,G改成红色,以G为节点进行右旋
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
//父节点在右边的
/**
* G
* U P(RED)
*/
//获取U
Entry<K, V> y = leftOf(parentOf(parentOf(x))); if (colorOf(y) == RED) {
//红父红叔的情况
/**
* G
* U(RED) P(RED)
*/
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
//把G当作新插入的节点继续进行迭代
x = parentOf(parentOf(x));
} else {
//红父黑叔,并且是右父的情况
/**
* G
* U(RED) P(RED)
*/
if (x == leftOf(parentOf(x))) {
//如果插入的X是左节点
/**
* G
* U(BLACK) P(RED)
* X
*/
x = parentOf(x);
//以P为节点进行右旋
rotateRight(x);
}
//右旋后
/**
* G
* U(BLACK) P(RED)
* X
*/
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
//以G为节点进行左旋
rotateLeft(parentOf(parentOf(x)));
}
}
}
//红黑树的根节点始终是黑色
root.color = BLACK;
}
其实就是一颗2-3-4树变种,红黑树详情可以看我上一篇
而且JDK8的hashMap链表后,链表的深度超过8也是转换成红黑树的存储,个人是认为转换成红黑树后,hashMap的扩容条件是有问题了,应该加入是否有红黑树的判断
JAVA的那些数据结构实现总结,实现,扩容说明的更多相关文章
- 20172302 《Java软件结构与数据结构》实验二:树实验报告
课程:<Java软件结构与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年11月5日 必修/选修: 必修 实验内容 (1)参 ...
- 20172301 《Java软件结构与数据结构》实验二报告
20172301 <Java软件结构与数据结构>实验二报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 ...
- 20172329 2018-2019-2 《Java软件结构与数据结构》实验二报告
20172329 2018-2019-2 <Java软件结构与数据结构>实验二报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 王文彬 学号:2017232 ...
- 20172301 《Java软件结构与数据结构》实验一报告
20172301 <Java软件结构与数据结构>实验一报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第三周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第三周学习总结 教材学习内容总结 本周内容主要为书第五章内容: 队列 线性集合(元素从一端加入,另一端删除) 先进先 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第四周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第四周学习总结 教材学习内容总结 本周内容主要为书第六章内容: 列表 有序列表(元素按照元素内在特性进行排序) 无序 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第二周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第二周学习总结 教材学习内容总结 本周内容主要为书第三章和第四章的内容: 第三章(以数组来替代栈的作用) 集合(聚集 ...
- 动图+源码,演示Java中常用数据结构执行过程及原理
最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...
- 动图+源码,演示 Java 中常用数据结构执行过程及原理
阅读本文大概需要 3.7 分钟. 作者:大道方圆 cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想 ...
- Java:集合类的数据结构
本文源自参考<Think in Java>,多篇博文以及阅读源码的总结 前言 Java的集合其实就是各种基本的数据结构(栈,队列,hash表等),基于业务需求进而演变出的Java特有的数据 ...
随机推荐
- Feedalyze - 让你听得见、听得清用户的反馈
满足用户需求,解决用户问题,获得适当报酬是商业成功最为重要的因素.然而扪心自问,当您推出新产品后,您真的在听.听得见.听得清用户的反馈么? 当今信息传播迅猛,渠道繁多,优秀产品随口碑效应供不应求,劣质 ...
- 鸿蒙WebSocket的使用竟如此简单
使用WebSocket建立服务器与客户端的双向连接,需要先通过createWebSocket()方法创建WebSocket对象,然后通过connect()方法连接到服务器.当连接成功后,客户端会收到o ...
- rust学习笔记(7)
crate 中文是货箱,这是我们编写自己的库或者程序的方式 库 使用rustc可以把一个文件编译为lib rustc --crate-type=lib rary.rs 构建的方式选择lib 编译出来的 ...
- AI+Web3:张三的未来机会地图
热点风暴:ETHDenver 2025掀起热潮 滑动微信的那一刻,张三愣住了.热搜上,ETHDenver大会简直是技术圈的春晚.AI和Web3,这两个曾经高高在上的概念,突然变得触手可及.大会透露的一 ...
- Windows 提权-密码搜寻
本文通过 Google 翻译 Password Hunting – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释 ...
- 【Linux】2.1 Linux入门
Linux入门 1. Linux介绍 Linux 是一款免费,开源,安全,高效,稳定,处理高斌发很强悍的操作系统 Linux创始人--linux(林纳斯) Linux主要发行版本 2. Unix与Li ...
- leetcode每日一题:酿造药水需要的最少总时间
引言 今天的每日一题原题是2255. 统计是给定字符串前缀的字符串数目,直接模拟,逐个匹配words中的字符串是否是s的前缀即可.更换成前几天遇到的更有意思的一题来写这个每日一题. 题目 给你两个 ...
- bash极简教程
今天看到消息,来自大神阮一峰的<bash脚本教程>开源发布了, 我也借此机会来总结个bash极简教程. 本文是一个更加简化的<bash极简教程>,告诉你什么时候需要使用bash ...
- 0x03 搜索与图论
搜索与图论 广度优先搜索\(BFS\) 概念 广度优先搜索(Breadth-First Search)是一种图遍历算法,用于在图或树中按层次逐层访问节点.它从源节点(起始节点)开始,首先访问源节点的所 ...
- 🎀Docker下Dubbo服务优雅上下线实现
简介 在Docker容器环境中部署基于Dubbo的服务时,实现服务的优雅上下线是至关重要的.这通常涉及到两个关键步骤:首先,确保服务能够从注册中心摘除,停止接受新的请求:其次,等待所有正在处理的请求完 ...