能沉淀下来的东西,往往都很基础,整理了下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的那些数据结构应用的更多相关文章

  1. 《Java程序设计与数据结构教程(第二版)》学习指导

    <Java程序设计与数据结构教程(第二版)>学习指导 欢迎关注"rocedu"微信公众号(手机上长按二维码) 做中教,做中学,实践中共同进步! 原文地址:http:// ...

  2. 20145205 java语言实现数据结构实验一

    数据结构实验要求 综合类实验设计3 已知有一组数据a1a2a3a4--anb1b2b3b4--bm,其中ai均大于bj,但是a1到an和b1到bm不是有序的,试设计两到三个算法完成数据排序,且把bj数 ...

  3. java中的数据结构(集合|容器)

    对java中的数据结构做一个小小的个人总结,虽然还没有到研究透彻jdk源码的地步.首先.java中为何需要集合的出现?什么需求导致.我想对于面向对象来说,对象适用于描述任何事物,所以为了方便对于对象的 ...

  4. [转]详细介绍java中的数据结构

    详细介绍java中的数据结构 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类.一起来看本文吧! 也许你已经熟练使用了java.util包里面的各 ...

  5. 详细介绍java中的数据结构

    详细介绍java中的数据结构 http://developer.51cto.com/art/201107/273003.htm 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个 ...

  6. 20162323周楠《Java程序设计与数据结构》第六周总结

    学号 2016-2017-2 <程序设计与数据结构>第六周学习总结 教材学习内容总结 继承:从已有类派生一个新类,是面向对象程序设计的一个特点 在Java中只支持单继承,不支持多继承 继承 ...

  7. Java程序设计与数据结构导论--读后感

    与我前面所读的<Java7基础教程>相比,此书不适合自学,更适合作为教材使用. 虽然此书完整覆盖了Java的知识点和数据结构的基础问题,并且对每个部分都做了基本说明.但是因为没有深入展开, ...

  8. 20172328 2018-2019《Java软件结构与数据结构》第一周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第一周学习总结 概述 Generalization 本周学习了软件质量.数据结构以及算法分析的具体内容,主要依托于所用教材 ...

  9. 20172328 2018—2019《Java软件结构与数据结构》第二周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第二周学习总结 概述 Generalization 本周学习了第三章集合概述--栈和第四章链式结构--栈.主要讨论了集合以 ...

随机推荐

  1. SQLite用法

    SQLite语法:http://blog.csdn.net/ejzhang/article/details/6224915#08 SQLite查询优化:1.http://www.eoeandroid. ...

  2. jmeter+ant+jenkins+mac使用HTML Publisher插件后查看html报告显示不正常

    Jenkins安全默认将以下功能关闭: 1.javascript2.html上的内置插件3.内置css或从其它站的css4.从其它站的图处5.AJAX 报告中有javascript,所以显示异常.解决 ...

  3. iOS 之 线性布局

    本来想自己写一个线性布局的类,看来不用了 ,网上已经有了,我先试试好不好用. https://github.com/youngsoft/MyLinearLayout 线性布局MyLinearLayou ...

  4. spring整合mybatis,springMVC的0配置文件方式

    0配置文件的形式主要是采用spring3.0提供的@configuration注解和spring容器在启动的时候会加载实现了WebApplicationInitializer的类,并调用其onStar ...

  5. Memcached操作以及用法

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached ...

  6. 9 Python+Selenium鼠标事件

    [环境信息] python3.6+Selenium3.0.2+Firefox50.0+win7 [ActionChains类鼠标事件的常用方法] 1.右击:context_click() 2.双击:d ...

  7. delphi的TFileStream 内存流

    一.文件 文本文件是以行为单位进行读.写操作的.文本文件只能单独为读或写而打开,在一个打开的文本文件上同时进行读.写操作是不允许的. 二.定义 FileStream: TFileStream; 三.打 ...

  8. C语言strstr()函数:返回字符串中首次出现子串的地址

    今天又学到了一个函数 头文件:#include <string.h> strstr()函数用来检索子串在字符串中首次出现的位置,其原型为:    char *strstr( char *s ...

  9. 支付宝 Android 版使用的开源组件

    支付宝 Android 版使用的开源组件 前言: 花了点时间整理了 支付宝 Android 客户端使用的开源组件,给需要的同学.在你不知道用什么开源框架的时候可以作下参考,毕竟支付宝是阿里的重量级产品 ...

  10. C++ 头文件系列(vector)

    简介 vector头文件包含vector的类模版以及该模版的显示特化版本vector< bool >. vector是C++容器库中非常通用的一种容器,如果你不知道该决定使用哪一种容器,或 ...