【java提高】---ArrayList源码
ArrayList源码
一、定义
public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess,Cloneable,java.io.Serializable
从中我们可以了解到:
- ArrayList<E>:说明ArrayList支持泛型。
- extends AbstractList<E> :继承了AbstractList。AbstractList提供List接口的骨干实现,以最大限度地减少“随机访问”数据存储(如ArrayList)实现Llist所需的工作。
- implements List<E>:实现了List。实现了所有可选列表操作。
- implements RandomAccess:表明ArrayList支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。
- implements Cloneable:表明其可以调用clone()方法来返回实例的field-for-field拷贝。
- implements java.io.Serializable:表明该类具有序列化功能。
二、构造函数
// 默认构造函数
ArrayList() // capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。
ArrayList(int capacity) // 创建一个包含collection的ArrayList
ArrayList(Collection<? extends E> collection)
三、ArrayList源码解析
import java.util.*; public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
// 序列版本号
private static final long serialVersionUID = 8683452581122892189L; // 保存ArrayList中数据的数组
private transient Object[] elementData; // ArrayList中实际数据的数量
private int size; // ArrayList带容量大小的构造函数。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 新建一个数组
this.elementData = new Object[initialCapacity];
} // ArrayList构造函数。默认容量是10。
public ArrayList() {
this(10);
} // 创建一个包含collection的ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} // 添加元素e
public boolean add(E e) {
// 确定ArrayList的容量大小
ensureCapacity(size + 1); // Increments modCount!!
// 添加e到ArrayList中
elementData[size++] = e;
return true;
} // 确定ArrarList的容量。
// 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”
public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
} // 返回ArrayList的实际大小
public int size() {
return size;
} // 返回ArrayList是否包含Object(o)
public boolean contains(Object o) {
return indexOf(o) >= 0;
} // 正向查找,返回元素的索引值
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
} // 返回ArrayList是否为空
public boolean isEmpty() {
return size == 0;
} // 返回ArrayList的Object数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
} // 返回ArrayList的模板数组。所谓模板数组,即可以将T设为任意的数据类型
public <T> T[] toArray(T[] a) {
// 若数组a的大小 < ArrayList的元素个数;
// 则新建一个T[]数组,数组大小是“ArrayList的元素个数”,并将“ArrayList”全部拷贝到新数组中
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass()); // 若数组a的大小 >= ArrayList的元素个数;
// 则将ArrayList的全部元素都拷贝到数组a中。
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
} // 获取index位置的元素值
public E get(int index) {
//判断数组是否越界
RangeCheck(index); return (E) elementData[index];
} // 将e添加到ArrayList的指定位置
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
} // 删除ArrayList指定位置的元素
public E remove(int index) {
RangeCheck(index); modCount++;
E oldValue = (E) elementData[index]; int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work return oldValue;
} // 删除ArrayList的指定元素
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;
} // 清空ArrayList,将全部的元素设为null
public void clear() {
modCount++; for (int i = 0; i < size; i++)
elementData[i] = null; size = 0;
} // 将ArrayList的“容量,所有的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // 写入“数组的容量”
s.writeInt(elementData.length); // 写入“数组的每一个元素”
for (int i=0; i<size; i++)
s.writeObject(elementData[i]); if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} // java.io.Serializable的读取函数:根据写入方式读出
// 先将ArrayList的“容量”读出,然后将“所有的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject(); // 从输入流中读取ArrayList的“容量”
int arrayLength = s.readInt();
Object[] a = elementData = new Object[arrayLength]; // 从输入流中将“所有的元素值”读出
for (int i=0; i<size; i++)
a[i] = s.readObject();
}
}
总结:
(01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。
(02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
(03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
(04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
参考博客:Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
水滴石穿,成功的速度一定要超过父母老去的速度! 少尉【3】
【java提高】---ArrayList源码的更多相关文章
- Java基础 ArrayList源码分析 JDK1.8
一.概述 本篇文章记录通过阅读JDK1.8 ArrayList源码,结合自身理解分析其实现原理. ArrayList容器类的使用频率十分频繁,它具有以下特性: 其本质是一个数组,因此它是有序集合 通过 ...
- Java中ArrayList源码分析
一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...
- Java集合ArrayList源码解读
最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见. :) 内部原理 ArrayList 的3个字段 priva ...
- Java集合-ArrayList源码解析-JDK1.8
◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...
- Java集合——ArrayList源码详解
) ArrayList 实现了RandomAccess, Cloneable, java.io.Serializable三个标记接口,表示它自身支持快速随机访问,克隆,序列化. public clas ...
- 【thinking in java】ArrayList源码分析
简介 ArrayList底层是数组实现的,可以自增扩容的数组,此外它是非线程安全的,一般多用于单线程环境下(Vector是线程安全的,所以ArrayList 性能相对Vector 会好些) Array ...
- Java基础—ArrayList源码浅析
注:以下源码均为JDK8的源码 一. 核心属性 基本属性如下: 核心的属性其实是红框中的两个: //从注释也容易看出,一个是集合元素,一个是集合长度(注意是逻辑长度,即元素的个数,而非数组长度) 其中 ...
- java.util.ArrayList源码分析
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...
- java的ArrayList源码摘要
ArrayList本质上是一组对象数组,ArrayList有三种构造方法 1.指定长度创建ArrayList,2.默认长度为10创建.3,用旧的集合创建一个ArrayList. 对ArrayList的 ...
- Java集合-ArrayList源码分析
目录 1.结构特性 2.构造函数 3.成员变量 4.常用的成员方法 5.底层数组扩容原理 6.序列化原理 7.集合元素排序 8.迭代器的实现 9.总结 1.结构特性 Java ArrayList类使用 ...
随机推荐
- mysql全日志(general log)的命令名称
在源码sql/sql_parse.cc中定义 const LEX_STRING command_name[]={ { C_STRING_WITH_LEN("Sleep") }, { ...
- vue2.0 带头冲锋(先穿鞋)
事先说明:这次截图纯手工敲打,可不容易了.刚学会站直,不穿鞋,不得直接摔个狗食屎.(皮糙肉厚也顶不住啊). 废话不多了 !开始学基础.学过anguler1.0 ,会比较容易学vue. 溶解使用的是 v ...
- 关于vue 框架与后台框架的混合使用的尝试
这几天我在研究前台框架和后台框架融合的问题,进行了一些尝试; 我前台选择的是 vue,当然也可以选择 react 等其他 mvvm 框架,不过 vue 对于我来说是最熟悉的; 后台话,我选择的是 ph ...
- phpcms v9 前台getshell脚本
phpcms v9 前台getshell脚本 用法:python phpcmsv9getshell.py http://baidu.com # -*- coding:utf-8 -*- ''' --- ...
- Vim常用操作-合并行。
刚接触 Vim 会觉得它的学习曲线非常陡峭,要记住很多命令.所以这个系列的分享,不会教你怎么配置它,而是教你怎么快速的使用它. 在开发时为了代码美观,经常会把属性用换行的方式显示. <el-di ...
- RAC(ReactiveCocoa)使用方法(二)
RAC(ReactiveCocoa)使用方法(一) RAC(ReactiveCocoa)使用方法(二) 上篇文章:RAC(ReactiveCocoa)使用方法(一) 中主要介绍了一些RAC中常见类的用 ...
- JavaEE中的MVC(三)定制Struts——命令模式
注:本文并不讲解Struts框架,只研究这种思想的使用 JavaEE中的MVC(五)定制Struts--Action跳转Jsp 在讲这个之前,先给你们看一下我服务器1.0版本的截图,是不是很可笑,看起 ...
- JAVA基础5——与String相关的系列(1)
与String相关的系列 String, 是JAVA中常见的一个引用类型,且其具有一定的特殊性. String类型被设置为final型,即不可继承,也就不可修改其中的实现. String可以改变吗 S ...
- 状态压缩dp第一题
标签: ACM 题目: Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; ...
- 2964:日历问题-poj
2964:日历问题 总时间限制: 1000ms 内存限制: 65536kB 描述 在我们现在使用的日历中, 闰年被定义为能被4整除的年份,但是能被100整除而不能被400整除的年是例外,它们不是闰 ...