分析轮子(一)-ArrayList.java
前言:之前也看过一些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 ? get(i)==null : 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的更多相关文章
- 分析轮子(五)- Vector.java
注:玩的是JDK1.7版本 一: 先上类图,从类图上看和 ArrayList.java 非常相像,可查看 分析轮子(一)-ArrayList.java 二:然后看源码,发现和 ArrayList.ja ...
- 分析轮子(四)- 我也玩一把 Serializable.java
前言:在写 分析轮子(一)-ArrayList.java 的时候曾经下过一个结论 “实现Serializable接口,表示ArrayList是可序列化的”,这个结论是以往学习的经验所得,并且平时在编程 ...
- 分析轮子(六)- LinkedList.java
注:玩的是JDK1.7版本 一:先上类的继承结构图 二:再看一下他的底层实现数据结构 三:然后从源码中找点好玩的东西 1)双向链表的结构构成元素,头指针.尾指针.节点信息(前向指针.后向指针.节点信息 ...
- 分析轮子(二)- << ,>>,>> (左移、右移、无符号右移)
前言:写 分析轮子(一)-ArrayList.java 的时候看到源码中有 int newCapacity = oldCapacity + (oldCapacity >> 1); 这样的代 ...
- 分析轮子(八)- List.java 各种遍历方式及遍历时移除元素的方法
注:玩的是JDK1.7版本 1:先尝栗子,再分析,代码简单,注释清晰,可自玩一下 /** * @description:测试集合遍历和移除元素的方式 * @author:godtrue * @crea ...
- 分析轮子(七)- RandomAccess.java
1:还是先上一个类的继承关系比较图吧! 2:看一下 RandomAccess.java 的源码,空空如也,什么都没有,那她有什么用处呢? /** * Marker interface used by ...
- 分析轮子(十)- HashMap.java 之概念梳理
注:玩的是JDK1.7版本 一:还是原来的风格,先上一下类的继承关系图,这样能够比较清楚的知道此类的相关特性 二:HashMap.java 的代码比较难看,所以,我看了几天,写的话也分开来写,这样能表 ...
- 分析轮子(九)- Cloneable.java
注:玩的是JDK1.7版本 一:Cloneable.java 接口也是标记接口,所以,它没有任何方法和属性,实现此接口表示的意思是:可以调用 Object.java 类的 clone() 方法,进行简 ...
- 学生管理系统开发代码分析笔记:jsp+java bean+servlet技术
1 序言 学习java web的时候很渴望有一份完整的项目给我阅读,而网上的大部分项目拿过来都无法直接用,好不容易找到了一个学生管理系统也是漏洞百出.在此,我将边修改边学习这份代码,并且加上完全的注释 ...
随机推荐
- TF之RNN:matplotlib动态演示之基于顺序的RNN回归案例实现高效学习逐步逼近余弦曲线—Jason niu
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt BATCH_START = 0 TIME_STEP ...
- 大数据技术 - MapReduce的Shuffle及调优
本章内容我们学习一下 MapReduce 中的 Shuffle 过程,Shuffle 发生在 map 输出到 reduce 输入的过程,它的中文解释是 “洗牌”,顾名思义该过程涉及数据的重新分配,主要 ...
- 利用Fiddler拦截接口请求并篡改数据
近期在测试一个下单的项目,出于安全角度考虑,测试了一个场景,那就是利用工具对接口进行拦截并篡改数据.将接口一拦截并篡改数据后,发现收货满满.开发默默接受了我的建议,并对代码进行了修改. 对于fiddl ...
- HTML使用的几个小知识点
本文主要分享几个网页前端的几个基础知识点,用于零碎的html知识学习,同时也是在实践中的一些心得.最后给出了几个小例子. 1. 网页编程初识 掌握基本的html标签以及CSS语法 学会查看网页的源代码 ...
- [LOJ6469]Magic
[LOJ6469]Magic 题目大意: 有\(n(n\le10^5)\)个物品,每个物品有一个权值\(w_i(w_i\le10^{18})\).求所有\(n\choose 2\)对物品\((i,j) ...
- vue动态切换页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- BZOJ2948 : [Poi2001]绿色游戏
维护一个保护集合$S$,表示哪些点$A$可能胜利. 首先将所有绿点加入$S$. $1.$对于一个不在$S$的$A$点,若它存在某个后继在$S$中,则将其加入$S$. $2.$对于一个不在$S$的$B$ ...
- 观光公交 [NOIP 2011] [思维推导]
Description 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号景点,随后依 ...
- JS_高阶函数(filter)
//2017/7/18 //高阶函数:filter. //filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素.和map()类似,Array的filter()也接收一 ...
- 关于js键盘事件的例子
JavaScript onkeydown 事件 用户按下一个键盘按键时会触发 onkeydown 事件.与 onkeypress事件不同的是,onkeydown 事件是响应任意键按下的处理(包括功能键 ...