前言:之前也看过一些JDK源码,不过没有留下痕迹,经久年月就淡忘了,现在的时机也差不多了,想再看一次,并且记录下来自己的感想,于是从自己使用最多最熟悉的地方开始!并且看的过程中,我希望自己思考一下如下的问题:

1:如果让我设计,我怎么玩?

2:原作者为什么这样设计?

3:它的底层实现是什么玩意?有什么特点?

4:平时使用的时候,需要注意些什么东西?

5:原设计有什么特别好玩的点?

注:玩的是JDK1.7版本

一:先上类的继承结构图

细细看上图,其实就能透露出一些关键的信息,比如:

1:实现Serializable接口,表示ArrayList是可序列化的

2:实现RandomAccess接口,表示ArrayList是可快速随机访问的

3:实现Cloneable接口,表示ArrayList是可以调用Object.clone方法的

4:实现Iterable接口,表示允许ArrayList使用迭代遍历的方式循环

二:再看一下他的底层实现数据结构

三:然后从源码中找点好玩的东西

从源码中可以看出ArrayList的底层数据结构是一个数组,所以,它所有的操作都是围绕着数组来玩的。

1)观察如下代码,我们可以了解到如下信息

private 表示不能被类外操作

transient 表示通过实现Serializable接口的方式来序列化时,被其标识的类变量可以不被序列化

Object[] 表示ArrayList的通用性

    /**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/
private transient Object[] elementData;

2)size表示数组中元素的个数,对于数组数据结构而言,数据长度相当重要

    /**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;

3)观察如下源码,我们可以看到如下信息

ArrayList的无参构造函数,初始化的数组对象是一个空数组

ArrayList的有参构造函数,初始化的对象是根据指定的空间大小来分配数组的空间的

ArrayList是一个动态扩展的数据集合从 grow 方法中可见一二,并且当它的空间不够的时候会扩展为(大概是这样他还有一些最大最小长度的判断逻辑): 原总长度+原总长度的一半

当然ArrayList的元素的值也是有限的最大是 Integer.MAX_VALUE

    /**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
    /**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
    /**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
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++; // overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
    /**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int 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);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
    /**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

4)观察如下源代码,可以看到ArrayList是可以放null的,并且删除元素涉及到数据的移位复制操作是比较耗费性能的

    /**
* Removes the first occurrence of the specified element from this list,
* if it is present. If the list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* <tt>i</tt> such that
* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
    /*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}

四:小结

通过观察ArrayList的源码,发现如下一些特点:

1:ArrayList的底层数据结构是数组,所有,数组这种数据结构的特点ArrayList应该也是具有的,这是他的本质

2:数组或者ArrayList这种数据结构的特点是,随机访问、循环遍历等性能好,指定位置插入或删除元素会涉及数组元素的复制,性能较差

3:ArrayList的底层数据是Object[],所以,具有很好的通用性,null也是可以存入ArrayList中的

4:ArrayList在添加元素的时候,首先会进行容量检测,如果不够会进行动态扩容

5:ArrayList使用的非常之多,使用起来也非常简单,不过看源码并不复杂,但是有些东西如果完全弄清楚也非易事,下面我会补充一些内容以供扫除阅读源码产生的一些障碍

分析轮子(一)-ArrayList.java的更多相关文章

  1. 分析轮子(五)- Vector.java

    注:玩的是JDK1.7版本 一: 先上类图,从类图上看和 ArrayList.java 非常相像,可查看 分析轮子(一)-ArrayList.java 二:然后看源码,发现和 ArrayList.ja ...

  2. 分析轮子(四)- 我也玩一把 Serializable.java

    前言:在写 分析轮子(一)-ArrayList.java 的时候曾经下过一个结论 “实现Serializable接口,表示ArrayList是可序列化的”,这个结论是以往学习的经验所得,并且平时在编程 ...

  3. 分析轮子(六)- LinkedList.java

    注:玩的是JDK1.7版本 一:先上类的继承结构图 二:再看一下他的底层实现数据结构 三:然后从源码中找点好玩的东西 1)双向链表的结构构成元素,头指针.尾指针.节点信息(前向指针.后向指针.节点信息 ...

  4. 分析轮子(二)- << ,>>,>> (左移、右移、无符号右移)

    前言:写 分析轮子(一)-ArrayList.java 的时候看到源码中有 int newCapacity = oldCapacity + (oldCapacity >> 1); 这样的代 ...

  5. 分析轮子(八)- List.java 各种遍历方式及遍历时移除元素的方法

    注:玩的是JDK1.7版本 1:先尝栗子,再分析,代码简单,注释清晰,可自玩一下 /** * @description:测试集合遍历和移除元素的方式 * @author:godtrue * @crea ...

  6. 分析轮子(七)- RandomAccess.java

    1:还是先上一个类的继承关系比较图吧! 2:看一下 RandomAccess.java 的源码,空空如也,什么都没有,那她有什么用处呢? /** * Marker interface used by ...

  7. 分析轮子(十)- HashMap.java 之概念梳理

    注:玩的是JDK1.7版本 一:还是原来的风格,先上一下类的继承关系图,这样能够比较清楚的知道此类的相关特性 二:HashMap.java 的代码比较难看,所以,我看了几天,写的话也分开来写,这样能表 ...

  8. 分析轮子(九)- Cloneable.java

    注:玩的是JDK1.7版本 一:Cloneable.java 接口也是标记接口,所以,它没有任何方法和属性,实现此接口表示的意思是:可以调用 Object.java 类的 clone() 方法,进行简 ...

  9. 学生管理系统开发代码分析笔记:jsp+java bean+servlet技术

    1 序言 学习java web的时候很渴望有一份完整的项目给我阅读,而网上的大部分项目拿过来都无法直接用,好不容易找到了一个学生管理系统也是漏洞百出.在此,我将边修改边学习这份代码,并且加上完全的注释 ...

随机推荐

  1. JavaEE 之 log4j

    1.log4j a.概念:一个非常优秀的开源日志记录工具 b.配置: ①src同目录下建立log4j.properties文件,书写: log4j.rootLogger=debug,appender1 ...

  2. P1967 货车运输

    P1967 货车运输最大生成树+lca+并查集 #include<iostream> #include<cstdio> #include<queue> #inclu ...

  3. 浅析js闭包

    闭包是一个老生常谈的问题,简单概括下闭包的形成的两个条件: 1.定义在函数内部 2.函数内部引用父层作用域变量 举一个最简单的例子: function test() { var a = 1; func ...

  4. Django 学习第五天——自定义过滤器及标签

    代码布局:(自定义的代码放在哪?) 1.创建某个 app 特有的: 在 app 目录下,创建 templatetags python包(文件夹): 再到 templatetags 文件夹下创建pyth ...

  5. 【C#】 break continue return 的区别

    static void Main(string[] args) { Console.WriteLine("使用break退出循环"); ; i < ; i++) { ) { ...

  6. elementUI的table组件实现setCurrentRow的滚动条定位效果

    在github上咨询了,直接给了代码: https://jsfiddle.net/tk37c5cb/14/

  7. BZOJ.3504.[CQOI2014]危桥(最大流ISAP)

    BZOJ 洛谷 这种题大多是多源多汇跑网络流.往返\(a_n/b_n\)次可以看做去\(a_n/b_n\)次,直接把危桥能走的次数看做\(1\). 先不考虑别的,直接按原图建模:危桥建双向边容量为\( ...

  8. RabbitMQ主题模式

    Send类 package topics; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; imp ...

  9. [CQOI2005]三角形面积并

    [CQOI2005]三角形面积并 题目大意: 求\(n(n\le100)\)个三角形的面积并. 思路: 自适应辛普森法,玄学卡精度可过. 源代码: #include<cmath> #inc ...

  10. React使用Styled-Componets来添加样式

    React使用Styled-Componets来添加样式 Styled-Comonents是用JS中ES6 语法的方式来管理CSS样式的一个组件,解决了在import CSS文件时样式重复 安装 项目 ...