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举例,加入自己的注释的理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//对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的扩容条件是有问题了,应该加入是否有红黑树的判断

 

相关文章
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--希尔排序
数据结构与算法(Java篇)笔记--希尔排序
|
23天前
|
存储 算法 Java
Java数据结构与算法-java数据结构与算法(二)
Java数据结构与算法-java数据结构与算法
66 1
|
1月前
|
缓存 算法 安全
Java集合框架:深入探究数据结构与算法的精华
Java集合框架:深入探究数据结构与算法的精华
|
7天前
|
Java API
编码的奇迹:Java 21引入有序集合,数据结构再进化
编码的奇迹:Java 21引入有序集合,数据结构再进化
14 0
|
20天前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解04-阻塞队列之PriorityBlockingQueue原理及扩容机制详解
1. **继承实现图关系**: - `PriorityBlockingQueue`实现了`BlockingQueue`接口,提供了线程安全的队列操作。 - 内部基于优先级堆(小顶堆或大顶堆)的数据结构实现,可以保证元素按照优先级顺序出队。 2. **底层数据存储结构**: - 默认容量是11,存储数据的数组会在需要时动态扩容。 - 数组长度总是2的幂,以满足堆的性质。 3. **构造器**: - 无参构造器创建一个默认容量的队列,元素需要实现`Comparable`接口。 - 指定容量构造器允许设置初始容量,但不指定排序规则。 - 可指定容量和比较
40 2
|
23天前
|
XML 存储 算法
Java数据结构与算法-java数据结构与算法(五)
Java数据结构与算法-java数据结构与算法
47 0
|
26天前
|
缓存 安全 Java
Java并发编程中的高效数据结构 - ConcurrentHashMap
本文将深入探讨Java并发编程中的一种高效数据结构 - ConcurrentHashMap。我们将详细介绍ConcurrentHashMap的基本原理,包括其设计思路、实现方式以及如何在多线程环境下提供高效的并发访问。同时,我们还将通过实例代码演示如何使用ConcurrentHashMap来优化并发程序的性能。
|
26天前
|
Java 数据库连接 API
Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API
Java 是一种广泛使用的、面向对象的编程语言,始于1995年,以其跨平台性、安全性和可靠性著称,应用于从移动设备到数据中心的各种场景。基础概念包括变量(如局部、实例和静态变量)、数据类型(原始和非原始)、条件语句(if、else、switch等)、函数、循环、异常处理、数据结构(如数组、链表)和面向对象编程(类、接口、继承等)。深入学习还包括包、内存管理、集合框架、序列化、网络套接字、泛型、流、JVM、垃圾回收和线程。构建工具如Gradle、Maven和Ant简化了开发流程,Web框架如Spring和Spring Boot支持Web应用开发。ORM工具如JPA、Hibernate处理对象与数
90 3
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--快速排序
数据结构与算法(Java篇)笔记--快速排序
|
1月前
|
机器学习/深度学习 算法 搜索推荐
数据结构与算法(Java篇)笔记--归并排序
数据结构与算法(Java篇)笔记--归并排序