热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

图解java_图解Java中的数据结构及原理!

作者:大道方圆cnblogs.comxdecodep9321848.html最近在整理数据结构方面的知识,系统化看了下Java中常用数据结构,突发奇想用动画来绘制数据

作者:大道方圆 cnblogs.com/xdecode/p/9321848.html

最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程。

主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList LinkedHashMap中的双向列表不再是回环的。

HashMap中的单链表是尾插, 而不是头插入等等, 后文不再赘叙这些差异, 本文目录结构如下:

eb0d15fb83fa8eb6d2d2514235b21bb1.gif

add(index, E)

这边有个小的优化, 他会先判断index是靠近队头还是队尾, 来确定从哪个方向遍历链入.

1         if (index <(size >> 1)) {

2             Node x &#61; first;

3             for (int i &#61; 0; i

4                 x &#61; x.next;

5             return x;

6         } else {

7             Node x &#61; last;

8             for (int i &#61; size - 1; i > index; i--)

9                 x &#61; x.prev;

10             return x;

11         }

5d8a35cba8ba5a4c1c1a9158b4015541.gif

靠队尾

1732f3ecfeaa1b879d44d66a13395be9.gif

get(index)

也是会先判断index, 不过性能依然不好, 这也是为什么不推荐用for(int i &#61; 0; i

07fde92d2e5da67b02757361b05fd5cc.gif

06b995c6ea79fa3973a4f5560176fecf.gif

remove(E)

e666873c397af96c0a3c6f63e6dcf2f3.gif

ArrayList

底层就是一个数组, 因此按序查找快, 乱序插入, 删除因为涉及到后面元素移位所以性能慢.

add(index, E)

297ec6e2da716399c28f0c144876ad01.gif

扩容

一般默认容量是10, 扩容后, 会length*1.5.

7315a72ab7b8fcbfb910fae08039e5ae.gif

remove(E)

循环遍历数组, 判断E是否equals当前元素, 删除性能不如LinkedList.

095af4dea729385228f229694865200b.gif

Stack

经典的数据结构, 底层也是数组, 继承自Vector, 先进后出FILO, 默认new Stack()容量为10, 超出自动扩容.

push(E)

c9ff88033494acc67ed711f2d212a514.gif

pop()

d348f8dca710852fca3284d63ea204a9.gif

后缀表达式

Stack的一个典型应用就是计算表达式如 9 &#43; (3 - 1) * 3 &#43; 10 / 2, 计算机将中缀表达式转为后缀表达式, 再对后缀表达式进行计算。推荐阅读&#xff1a;Java 程序员必须掌握的 8 道数据结构面试题&#xff0c;你会几道&#xff1f;

中缀转后缀

数字直接输出

栈为空时&#xff0c;遇到运算符&#xff0c;直接入栈

遇到左括号, 将其入栈

遇到右括号, 执行出栈操作&#xff0c;并将出栈的元素输出&#xff0c;直到弹出栈的是左括号&#xff0c;左括号不输出。

遇到运算符(加减乘除)&#xff1a;弹出所有优先级大于或者等于该运算符的栈顶元素&#xff0c;然后将该运算符入栈

最终将栈中的元素依次出栈&#xff0c;输出。

a1f220b775879cccb760f723ad20ec1e.gif

计算后缀表达

遇到数字时&#xff0c;将数字压入堆栈

遇到运算符时&#xff0c;弹出栈顶的两个数&#xff0c;用运算符对它们做相应的计算, 并将结果入栈

重复上述过程直到表达式最右端

运算得出的值即为表达式的结果

9a1efa2401dc98077ffc9d95ad1203ee.gif

队列

与Stack的区别在于, Stack的删除与添加都在队尾进行, 而Queue删除在队头, 添加在队尾.

ArrayBlockingQueue

生产消费者中常用的阻塞有界队列, FIFO.

put(E)

3a11f8bd21ca91b08ea1bd3b6cff9fd1.gif

put(E) 队列满了

1         final ReentrantLock lock &#61; this.lock;

2         lock.lockInterruptibly();

3         try {

4             while (count &#61;&#61; items.length)

5                 notFull.await();

6             enqueue(e);

7         } finally {

8             lock.unlock();

9         }

bdd08e3c0b6268d13a8dc9d9d7cc1429.gif

take()

当元素被取出后, 并没有对数组后面的元素位移, 而是更新takeIndex来指向下一个元素.

takeIndex是一个环形的增长, 当移动到队列尾部时, 会指向0, 再次循环.

1     private E dequeue() {

2         // assert lock.getHoldCount() &#61;&#61; 1;

3         // assert items\[takeIndex\] !&#61; null;

4         final Object\[\] items &#61; this.items;

5         &#64;SuppressWarnings("unchecked")

6         E x &#61; (E) items\[takeIndex\];

7         items\[takeIndex\] &#61; null;

8         if (&#43;&#43;takeIndex &#61;&#61; items.length)

9             takeIndex &#61; 0;

10         count--;

11         if (itrs !&#61; null)

12             itrs.elementDequeued();

13         notFull.signal();

14         return x;

15     }

8e9498c9f90c0051399924ec2cf60248.gif

HashMap

最常用的哈希表, 面试的童鞋必备知识了, 内部通过数组 &#43; 单链表的方式实现. jdk8中引入了红黑树对长度 > 8的链表进行优化, 我们另外篇幅再讲。推荐阅读&#xff1a;Java 程序员必须掌握的 8 道数据结构面试题&#xff0c;你会几道&#xff1f;

put(K, V**)**

0573ae22cd026ad63a45922475e84537.gif

put(K, V) 相同hash值

7bf4e39c37df9196985d954fd599d08f.gif

resize 动态扩容

当map中元素超出设定的阈值后, 会进行resize (length * 2)操作, 扩容过程中对元素一通操作, 并放置到新的位置。推荐阅读&#xff1a;Java 程序员必须掌握的 8 道数据结构面试题&#xff0c;你会几道&#xff1f;

具体操作如下:

在jdk7中对所有元素直接rehash, 并放到新的位置.

在jdk8中判断元素原hash值新增的bit位是0还是1, 0则索引不变, 1则索引变成"原索引 &#43; oldTable.length".

1     //定义两条链

2     //原来的hash值新增的bit为0的链&#xff0c;头部和尾部

3     Node loHead &#61; null, loTail &#61; null;

4     //原来的hash值新增的bit为1的链&#xff0c;头部和尾部

5     Node hiHead &#61; null, hiTail &#61; null;

6     Node next;

7     //循环遍历出链条链

8     do {

9         next &#61; e.next;

10         if ((e.hash & oldCap) &#61;&#61; 0) {

11             if (loTail &#61;&#61; null)

12                 loHead &#61; e;

13             else

14                 loTail.next &#61; e;

15             loTail &#61; e;

16         }

17         else {

18             if (hiTail &#61;&#61; null)

19                 hiHead &#61; e;

20             else

21                 hiTail.next &#61; e;

22             hiTail &#61; e;

23         }

24     } while ((e &#61; next) !&#61; null);

25     //扩容前后位置不变的链

26     if (loTail !&#61; null) {

27         loTail.next &#61; null;

28         newTab\[j\] &#61; loHead;

29     }

30     //扩容后位置加上原数组长度的链

31     if (hiTail !&#61; null) {

32         hiTail.next &#61; null;

33         newTab\[j &#43; oldCap\] &#61; hiHead;

34     }

bbff4598c92b1c87a30cce3248b44234.gif

LinkedHashMap

继承自HashMap, 底层额外维护了一个双向链表来维持数据有序. 可以通过设置accessOrder来实现FIFO(插入有序)或者LRU(访问有序)缓存.

put(K, V)

57b78fa22803ef307f81f96568baefd5.gif

get(K)

accessOrder为false的时候, 直接返回元素就行了, 不需要调整位置.

accessOrder为true的时候, 需要将最近访问的元素, 放置到队尾.

dbb6830f3c8a8896c023311b31a3fb83.gif

removeEldestEntry 删除最老的元素

0d6f520efa751f25dbb31d4ac5dbcac5.gif

(完)

推荐去我的博客&#xff1a;

觉得不错&#xff0c;别忘了点赞&#43;转发哦&#xff01;



推荐阅读
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
author-avatar
阿吉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有