目录

  • Java源码阅读学习后的浅析和感悟(JKD篇)
    • - 为什么阅读源码
  • 集合框架类
    • - 为什么会要引入集合
    • - 集合结构图(部分)
    • ArrayList集合源码分析
      • - 扩容机制
        • - 关键方法解释(DEFAULTCAPACITY_EMPTY_ELEMENTDATA-->默认为空的elementData数组)
        • 1.private void ensureCapacityInternal(int minCapacity)
        • 2.private static int calculateCapacity(Object[] elementData, int minCapacity)
        • 3.private void ensureExplicitCapacity(int minCapacity)
        • 4.private void grow(int minCapacity)★
        • 5.总结
    • LinkedList集合源码分析
      • - 增删改查分析
        • - 链表基本插入删除操作演示(动图)

Java源码阅读学习后的浅析和感悟(JKD篇)

- 为什么阅读源码

一、感觉现在学习Java就是在学她的各种API如何调用,时间长了就觉得Java很枯燥失去了热情。二、好奇这些API在底层如何实现的,就比如pow(a,b)难道就是b个a相乘?顺便再记个笔记方便复习。三、更想学习这些大佬们的思路,到底是什么样的人才能搞出来这些东西!四、个人原因,可能是感情问题哈哈哈哈哈,我突然发现我在感情上一旦出现情绪波动,唯一能转移情绪的可能就是技术了!

集合框架类

- 为什么会要引入集合

答:为了更方便更高效的存储多个数据。在初学的时候,我们都知道在集合出现之前方便存储多个数据的是数组,但是它总归有自己的局限性:1.长度,在存储对象时由于长度的不确定性使得数组不太适用。因为数组一旦指定了长度就无法更改。2.存储特性,顺序存储且可重复。故对于需要无序的或需要去重的存储就带来了极大的不便。3.增加、删除,在增删时效率太低。在我们学数据结构中可知,数组是顺序表的结构,数组除了在末尾删除时不需要移动其他元素,在别的地方都需要。

- 集合结构图(部分)

ArrayList集合源码分析

- 扩容机制

如何扩容:一、ArrayList中创建了一个Object型的数组elementData[],往后的绝大多数操作都是以elementData数组为基础。二、当ArrayList对象是用ArrayList()方法被创建时,elementData的初始容量为 0,第一次向里面添加元素时,其容量会扩容到 10,如果需要再次扩容,则扩容的容量时当前容量的1.5倍。三、当ArrayList对象是用ArrayList(int)方法被创建时,则容量为指定容量大小,如果再次扩容,容量是前一次的1.5倍。下面给出所要用到的方法、其解释和自己学习后的看法。(变量size-->索引)
  • 构造方法
// ArrayList(int)
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}//ArrayList()
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//ArrayList(Collection<? extends E> c)
public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}
  • 插入数据

public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;}public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1);  // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}

- 关键方法解释(DEFAULTCAPACITY_EMPTY_ELEMENTDATA–>默认为空的elementData数组)

1.private void ensureCapacityInternal(int minCapacity)

private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}
该方法用于计算elementData的最小容量。

2.private static int calculateCapacity(Object[] elementData, int minCapacity)

private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}
注:DEFAULT_CAPACITY默认扩容容量为 10
该方法 1.先判断这个数组的容量是否为 0,如果是 0,说明他用了无参构造器创建了该对象,再用了Matn.max(a,b)去最大值的方法返回给函数头。如果不为 0,则直接返回给函数头。
该方法的目的就是为了判别创建该对象时是否指定了其容量。

3.private void ensureExplicitCapacity(int minCapacity)

private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}
该方法为了明确最小容量是否足够当前的数据进入。
if (minCapacity - elementData.length > 0) 这段话的意思就是如果最小容量(其实就是指当前集合内有效元素的个数)大于了数组的长度说明容量不够了,需要扩容了故他就往下走,走到grow(minCapacity)方法中去。

4.private void grow(int minCapacity)★

private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);}
这一步才是真正对其进行扩容的步骤。
这一段的逻辑其实并不难但是很妙!
int oldCapacity = elementData.length  他把数组的长度给了这个扩容前的容量(oldCapacity)
int newCapacity = oldCapacity + (oldCapacity >> 1)  这段话是先把扩容前的容量扩容1.5呗然后赋给扩容后的容量(newCapacity ) 这里的位运算就用的很妙 oldCapacity >> 1 == oldCapacity / 2
if (newCapacity - minCapacity < 0)newCapacity = minCapacity;  这段话就是进行修补了,如果新容量比最小容量还小,那还不如用这个最小容量。
if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity); 这句话应该就是防止数组无限扩容。
elementData = Arrays.copyOf(elementData, newCapacity);  最后用了这个拷贝的方法,他在保留了原有数据的基础上再对数组进行扩容。

5.总结

第一次学习源码,真的是满嘴卧槽,很多地方太妙了。虽然自己的水平太难达到这种地步,但是看大牛前辈们留下的精华也是一种享受!!但是自己觉得这里面也有些不足,比如在用add()方法时,他每次都对当前容量进行判断是否需要扩容,如果我时批量添加元素也就是我添加n次他就判断n次,这样可能就会使得效率略低,做了一些无用功,但是还是不妨碍大佬们的这些发光的技术精华!(个人感受)

LinkedList集合源码分析

- 增删改查分析

LinkedList本质上就是一个(双向)链表,其优点:一、增加和删除的操作效率高,相比于数组,其时间复杂度为O(n)而链表则为O(1)二、不受大小限制,拓展性强。三、内存利用率高,只有在创建时才占用内存,不会对内存造成浪费。

- 链表基本插入删除操作演示(动图)

插入

删除

Java源码阅读学习后的浅析和感悟(JDK篇)(持续更新)相关推荐

  1. Java源码阅读之String(4)

    Java源码阅读之String(4) 这一篇博客主要阅读String类的查找和替换相关的方法. /**查询当前对象的哈希码,如果当前对象没有计算过哈希码*则计算当前对象的哈希码并赋值给当前对象的has ...

  2. Java源码阅读的真实体会(一种学习思路)

    刚才在论坛不经意间,看到有关源码阅读的 帖子 .回想自己前几年,阅读源码那种兴奋和成就感( 1 ),不禁又有一种激动.  源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我 ...

  3. 走过的路-java源码阅读之路

    源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 一.人生三种境界: 1.昨夜西风凋碧树,独上高楼望尽天涯路.           2.衣带渐宽终不悔,为伊消得人憔悴.           ...

  4. Java源码阅读的真实体会

    刚才在论坛不经意间,看到有关源码阅读的[url=http://www.iteye.com/topic/854647]帖子[/url].回想自己前几年,阅读源码那种兴奋和成就感([url=http:// ...

  5. Vue 源码阅读学习(三)

    第三节:函数柯里化与渲染模型 嘿,朋友们,本节是 Vue 源码阅读的第三讲.Vue 源码阅读系列得到了赞赏,我很高兴,同时希望大家可以给予反馈!我虚心接纳您的意见! 如果没有看之前的第一讲和第二讲的内 ...

  6. 讲解java源码_Java学习之Java源码讲解

    关于Java中源码的学习,是不少同学头疼的知识点.本文整理了JAVA源码学习的八大要点,分别是基础知识.面向对象.异常处理.集合.综合类核心代码.JAVA8新特性.Input/Output和Java小 ...

  7. Java源码阅读(类图自动生成工具)

    菜鸟上路,在有了基础以后,总需要去阅读大量的优秀的源码,但在面对一个项目工程大量的代码不知道怎么下手.只是跟着敲代码,我觉得这个方法不太妥当. 我是个方法论者,在收集查阅了大量的资料后发现画代码结构图 ...

  8. 【10.24】Java源码基础学习

    HashMap源码学习 putHashMap方法 将一个集合map中的哈希映射插入档期的哈希表中 首先对原表的大小进行扩展[注意最终的大小由有效载荷大小和载入因子决定,最终的大小一定大于有效载荷大小] ...

  9. java源码阅读Object

    1 类注释 Class {@code Object} is the root of the class hierarchy. Every class has {@code Object} as a s ...

最新文章

  1. 测试向量是否包含给定元素
  2. golang中的WaitGroup
  3. java反射 获取局部变量_Java反射:如何获取变量的名称?
  4. python实现requests访问接口,比如es接口
  5. 4 操作系统第二章 进程管理 进程控制、通信
  6. Windows Phone开发(44):推送通知第二集——磁贴通知
  7. 我所熟悉的网站负载均衡技术之硬件篇
  8. alias自定义别名
  9. 新建的mvn项目目录结构问题
  10. php阴影效果,css阴影效果:css边框阴影如何设置?
  11. 分享:skalibs 1.3.0 发布,低级的 C 程序库
  12. Geodesic Distance(测地距离)
  13. 金盾播放器android安卓,金盾高级视频加密系统跨平台播放器Android安卓安装步骤.doc...
  14. 内网IP可以申请SSL证书吗
  15. 全球四大国际反垃圾邮件组织介绍
  16. 某马python day03
  17. C#为什么读作C Sharp
  18. Android Studio初学者实例:RecyclerView学习--模仿今日头条
  19. Android 画布使用之电子签名
  20. 爬取裁判文书网(一)

热门文章

  1. HBase 高性能获取数据(多线程批量式解决办法) + MySQL和HBase性能测试比较
  2. php鼠标跟随特效,JS实现鼠标跟随特效
  3. 5G NR调度技术简介
  4. 5 个鲜为人知的黑科技网站,强大到不敢想象
  5. siggraph2008 papers
  6. vc2008 错误:对象不支持此属性或方法
  7. (一) 5G NR协议 - PDCCH
  8. 第七届数据挖掘、通信与信息技术国际会议征稿通知(DMCIT 2023)
  9. 二维卡通动画制作学习教程
  10. TortoiseGit下载指定文件