jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手。

ArrayList类定义:

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
span.s1 { color: #931a68 }

public class ArrayList<E> extends AbstractList<E> implements List<E>

ArrayList基本属性:

 /**
     * Default initial capacity.(默认初始化大小)
     */
    private static final int DEFAULT_CAPACITY = 10;
    /**
     * Shared empty array instance used for empty instances.
     * 空数组,当调用无参数构造函数的时候默认给个空数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 真正存储数据的数组
     */
    private transient Object[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     * 所存储数据的数量
     */

ArrayList的add方法:

/**
     * Appends the specified element to the end of this list.
     * 插入数据,每一次都是从末尾插入
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
  
  private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) { //此处表示若为空数组
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
 private void ensureExplicitCapacity(int minCapacity) {
     modCount++;//jdk源码阅读笔记之java集合框架(三)(modCount)
       if (minCapacity - elementData.length > 0)
            /**
        * minCapacity=size+1
        * 只用当数组实际存储元素数量+1大于数组长度是,需扩容
        */
        grow(minCapacity);
    }
    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     * 提高数组容量以确保至少能够存储minimum数量的数据
     */
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;

     //带符号右移等价于除以2,所以每一次扩容之后,数组的长度为原来的1.5倍。
        int newCapacity = oldCapacity + (oldCapacity >> 1);

        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //由于扩容之后产生了新数组,此处是新老数组之间数据的转移
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

ArrayList的remove方法:

remove方法分为 remove(Object o) 与 remove(int index)。俩方法类似,所以任挑其一进行分析。

 /**
     * 移除指定下标的元素
     */
    public E remove(int index) {
        rangeCheck(index);//下标越界检查

        modCount++; //"http://www.cnblogs.com/jw93/p/6845825.html"详细介绍
        E oldValue = elementData(index);

        /**
         * 移除某一元素之后,需要将该元素后面的元素向前移动
         * numMoved表示需要移动的元素个数
         */
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);//此处为native方法
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
    /**
     * 下标越界检查
     */
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));//抛出数组下标越界
    }
    /**
     * 抛出异常时详细信息
     */
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #0326cc }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; min-height: 25.0px }
span.s1 { color: #931a68 }
span.s2 { color: #000000 }
span.s3 { color: #0326cc }
span.s4 { text-decoration: underline }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #0326cc }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; min-height: 25.0px }
span.s1 { color: #931a68 }
span.s2 { color: #000000 }
span.s3 { color: #0326cc }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; min-height: 25.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #4e9072 }
span.s1 { color: #931a68 }
span.s2 { color: #0326cc }
span.s3 { color: #000000 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #4f76cb }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #4e9072 }
span.s1 { color: #000000 }
span.s2 { color: #91afcb }
span.s3 { color: #931a68 }
span.s4 { color: #0326cc }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #4f76cb }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
span.s1 { color: #000000 }
span.s2 { color: #91afcb }
span.s3 { color: #9293af }
span.s4 { color: #5158cb }
span.s5 { color: #931a68 }
span.s6 { color: #0326cc }
span.s7 { color: #4e9072 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #4f76cb }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; color: #931a68 }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco; min-height: 25.0px }
span.s1 { color: #000000 }
span.s2 { color: #0326cc }
span.s3 { color: #4f76cb }
span.s4 { color: #931a68 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
span.s1 { color: #931a68 }

时间: 2024-09-30 16:40:52

jdk源码阅读笔记之java集合框架(二)(ArrayList)的相关文章

jdk源码阅读笔记之java集合框架(一)(基础篇)

结合<jdk源码>与<thinking in java>,对java集合框架做一些简要分析(本着实用主义,精简主义,遂只会挑出个人认为是高潮的部分). 先上一张java集合框架的简图: 会从以下几个方面来进行分析: java 数组; ArrayList,LinkedList与Vector; HashMap; HashSet 关于数组array: 数组的解释是:存储固定大小的同类型元素.由于是"固定大小",所以对于未知数目的元素存储就显得力不从心,遂有了集合.

jdk源码阅读笔记之java集合框架(四)(LinkedList)

关于LinkedList的分析,会从且仅从其添加(add)方法入手. 因为上一篇已经分析过ArrayList,相似的地方就不再叙述,关注点在LinkedList的特点. 属性: /** *链表头 */ transient Node<E> first; /** * 链表尾 */ transient Node<E> last; 从以上两个属性可以得出LinkedList是基于双向链表实现的. 节点代码(无需过多解释): private static class Node<E>

JDK源码阅读(一):Object源码分析

最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 hashCode 方法 toString 方法 finalize 方法 registerNatives 方法 1. Object结构图 2. 类构造器 ??类构造器是创建Java对象的方法之一.一般我们都使用new关键字来进行实例,还可以在构造器中进行相应的初始化操作. ??在一个Java类中必须存在一个

JDK源码阅读(三):ArraryList源码解析

今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 一般来讲文章开始应该先介绍一下说下简介.这里就不介绍了 如果你不知道ArrayList是什么的话就没必要在看了.大致讲一下一些常用的方法 2.继承结构 ArrayList源码定义: ArrayList继承结构如下: Serializable 序列化接口 Cloneable 前面我们在看Object源

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa