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

article/2025/9/19 10:35:42

目录

  • 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)二、不受大小限制,拓展性强。三、内存利用率高,只有在创建时才占用内存,不会对内存造成浪费。

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

插入
在这里插入图片描述
删除
在这里插入图片描述


http://chatgpt.dhexx.cn/article/MpgJZN2B.shtml

相关文章

JDK源码系列 下载源码

为什么要写这个系列的文章呢&#xff1f; 因为我发现在工作中新来的Coder&#xff0c;它们往往Java基础都不牢固&#xff0c;却高谈阔论一些分布式事务&#xff0c;分布式场景。如果项目交给他们来做&#xff0c;未免让人感到有些担忧。包括我本人&#xff0c;对Java基础也掌握…

java学习线路(基础,源码,项目,实战)

如需获取以下学习资源请关注公众号&#xff1a;Java编程指南 我们为自学者编程的或初学java的小伙伴们准备了一整套完整的学习资源和文章&#xff0c;还有我自己在自学路上的一些总结和学习线路&#xff0c;希望能帮到小伙伴们&#xff0c;如果有什么疑问的地方也可以加小编的…

java基础源码

HashMap 第一部分 基础入门 1. 数组的优势、劣势 内存地址连续&#xff0c;可以通过下标常数时间复杂度O(1)获取元素&#xff0c;但是增加和删除元素时间复杂度为O(n)。 数组长度大小固定&#xff0c;如果需要扩容&#xff0c;需要重新申请一个数组&#xff0c;将原数组元素…

总结:JDK源码

一、JDK源码下载 地址&#xff1a;http://jdk.java.net/java-se-ri/8 选择版本&#xff0c;下载 RI Source Code 代码路径在:/openjdk/jdk/src/windows/native 对应着java中的类名 如&#xff1a;jdk 中SocketOutputStream中的write0的native方法 /openjdk/jdk/src/windows…

JAVA JDK 源码学习

JAVA JDK 源码学习 &#xff0c;以1.8为例&#xff0c;按照下面图片顺序依次学习&#xff1a; applet ,awt,beans,io,lang,math,net,nio,rmi,security,sql,text,time,util 第一课&#xff0c;广泛认知它们 1 applet Java applet 为使用Java语言编写的一些程序&#xff0c;可以…

JDK源码学习

Java集合框架之Collection集合 http://www.leocook.org/category/#java Java的集合框架分两大系Collection系和Map系&#xff0c;之所以要分开是因为Collection内存储的是线性集合&#xff0c;而 Map的元素是以键值对&#xff08;Key-Value&#xff09;的形式存的。其实Map和…

如何阅读Java源码?

阅读Java源码的前提条件&#xff1a; 1、技术基础 在阅读源码之前&#xff0c;我们要有一定程度的技术基础的支持。 假如你从来都没有学过Java&#xff0c;也没有其它编程语言的基础&#xff0c;上来就啃《Core Java》&#xff0c;那样是很难有收获的&#xff0c;尤其是《深入J…

JDK源码学习-基础

JDK源码学习 目录 基础 1. 安装 1.1 下载JDK 1.2 配置环境变量 1.3 验证 2. 简单的程序 2.1 编写代码 2.2 编译文件 2.3 执行类 3. java基本类型 基础 1. 安装 1.1 下载JDK Java下载地址&#xff1a;https://www.oracle.com/technetwork/java/javase/downloads/in…

bug修复---同时触发mousedown事件和touchstart事件

这两天遇到一个bug&#xff0c;每次点击下方键盘时&#xff0c;点击一次数字&#xff0c;文本框中会出现两次重复值&#xff0c;如下所示&#xff1a; 而且console中还有以下报错信息&#xff1a; 查看项目代码&#xff0c;代码如下&#xff1a; <ul><liv-for"…

Vue下 touchstart touchend 事件无效失效解决办法

Vue下 touchstart touchend 事件无效失效解决办法 <van-button:disabled"isLoading"plaintype"info"touchstart.native.prevent"touchstart"touchend.native.prevent"touchend"style"width:40%;height: 40px;"round>对…

触屏touchstart 与 click

设计效果&#xff1a;当手指点击或触摸红框线menuList之外的部分时&#xff0c;弹框menuList消失。 问题&#xff1a;在优化触屏版的时候发现如图问题&#xff0c;当menuList弹出&#xff0c;手指触摸屏幕向下滑动时&#xff0c;menuList弹框不消失&#xff0c;只有手指点击men…

移动端事件touchstart touchmove touchend 动画事件 过渡事件

在移动端新增了touch事件&#xff0c;因为手指的行为叫做“触摸”&#xff0c; 鼠标的行为叫做“点击” 但是它仍然支持点击事件&#xff0c;有300ms的延迟&#xff0c;检测是否双击 移动端的三个事件 touchstart&#xff1a;触摸开始 绑定方式&#xff1a; dom.addEve…

微信小程序、uniapp使用touchstart和touchmove左右滑动删除。以及解决上下抖动问题。

展示效果图直接上代码 <viewv-for"(item, index) in arr":key"item.id"touchstart"touchstart($event)"touchmove"touchmove(index, $event)":class"[touch-item, item.isTouchMove ? touch-move-active : ]" ><…

html按键使用touch,HTML touchstart事件用法及代码示例

每当用户触摸HTML元素时&#xff0c;就会使用touchstart事件执行脚本。触摸特定元素时&#xff0c;如果touchstart事件与之关联&#xff0c;则可以使用它触发javascript函数。 注意&#xff1a;touchstart事件仅在触摸屏设备上起作用。 用法: object.ontouchstart myScript; 以…

JavaScript touch 事件 touchstart touchmove touchend

JavaScript touch 事件 touchstart touchmove touchend MDN 官方文档&#xff1a; https://developer.mozilla.org/en-US/docs/Web/API/Touch_events 一、touch 事件有哪些 页面中的 touch 事件一般在移动端使用&#xff0c;pc 端是没有效果的。 touch 相关的事件有四个 touc…

触摸事件(touchstart、touchmove和touchend)

触摸事件(touch)会在用户手指放在屏幕上面的时候、在屏幕上滑动的时候或者是从屏幕上移开的时候出发。下面具体说明 touchstart事件&#xff1a;当手指触摸屏幕时候触发&#xff0c;即使已经有一个手指放在屏幕上也会触发。 touchmove事件&#xff1a;当手指在屏幕上滑动的时候…

Vue 绑定使用 touchstart touchmove touchend

今天要做一个页面div长按后触发事件&#xff0c;简单学习后实现如下&#xff1a; 先看代码&#xff1a; <template><div><div class"test" touchstart"gtouchstart()" touchmove"gtouchmove()" touchend"gtouchend()"…

H5移动端 利用touchstart 达到长按事件

一开始的没加.native ,结果长按事件不会触发, 原因是: 给vue组件绑定事件时候&#xff0c;必须加上native &#xff0c;否则会认为监听的是来自Item组件自定义的事件等同于在子组件中: 子组件内部处理click事件然后向外发送click事件: semit"dlick”.fn) //长按事件&am…

javaScript-touch事件详解(touchstart、touchmove和touchend)-滑动事件案例

HTML5中新添加了很多事件&#xff0c;但是由于他们的兼容问题不是很理想&#xff0c;应用实战性不是太强&#xff0c;所以在这里基本省略&#xff0c;咱们只分享应用广泛兼容不错的事件&#xff0c;日后随着兼容情况提升以后再陆续添加分享。今天为大家介绍的事件主要是触摸事件…

「移动端」touch事件,touchEvent对象

随着智能手机普及&#xff0c;有越来越多的手机网页和网页版游戏&#xff0c;手机触摸、移动、旋转等等&#xff0c;多种操作。一般电脑的人机交互靠的是鼠标&#xff0c;而手机用的就是触摸。区别有&#xff1a; PC 端一个电脑只能有一个鼠标&#xff0c;而移动端有多点触摸。…