ArrayList 底层是有数组实现,实际上存放的是对象的引用,而不是对象本身。当使用不带参的构造方法生成ArrayList对象时,实际会在底层生成一个长度为10的数组

当添加元素超过10的时候,会进行扩容 基本上是原来的1.5倍  oldlenth+(oldlenth>>1) 1.5oldlength

>> 表示右移  10>>1(000 1010)右移一位为 5(000 0101)

我们来看下源码

ArrayList a = new ArrayList(); 新建一个arraylist 点进去会出现

 /**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}

  头说明非常清楚,创建一个空的list,初始化他的长度

  /**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10; /**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {}; /**
* 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;

  DeFAULT_CAPACITY:是某认的长度10

  EMPTY_ELEMENTDATA:是list底层实现的数组

  transient Object[] elementData:存储数组元素的缓冲区,arraylist的容量是这个数组的长度,任何arraylist与elementData=EMPTY_ELEMENTDATA将会被扩展到添加第一个元素时的DEFAULT_CAPACITY

  

  transient关键字 修饰 表示在序列化的时候,被修饰的不会被序列化。

但是在arraylist中不是这样的,arraylist实现了序列化的writeObject()可指定序列化,arrayList将强制把elementData序列化,但是arryaList内部序列化的时候,因为初始

容量有10 ,但是我可能只有5个元素,那么剩下的就会是空值,在序列化的时候会把空值序列化进去,那么就没有意义,如果直接标记序列化则会把空值序列化进去,用transient修饰后然后重写writeObject()方法将其序列化,只序列化存储元素而不是整个数组,这样可以降低序列化的传输量,从而来提示速度

 /**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that
* is, serialize it).
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
* instance is emitted (int), followed by all of its elements
* (each an <tt>Object</tt>) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}

  这里会去根据size的长度去遍历,然后将对应值取出来序列化

boolean add方法 是将改对象加入到数据的最末端

void add(int index,E element)方法则是要从指定位置+1开始往后使用arraycopy方法赋值数组操作,之后在对对应元素赋值

void add方法

 /**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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++;
}

boolean add方法

  /**
* 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);
}

我们来一句一句的分析

进入add方法首先就是ensureCapacityInternal(size+1)设置内部缓冲区,在当前基础上+1,然后将元素添加到数组中

ensureCapacity()方法

  首先会判断数组对象是不是初始化数组,如果是的话,则会用初始化值也就是默认的长度10和我们现在传给他的长度做对比

如果传给他的值大于10则minCapacity最小容量为传的值,反之则为10.然后去设置缓冲区大小进入 ensureExplicitCapacity(minCapacity);

ensureExplicitCapacity(minCapacity)

  首先 modCount会自增,然后判断传过来的最知晓容量是否大于现有数组的长度,如果大于则扩容进入grow(minCapacity)方法

gorw(minCapacity)

   方法中,会想当前数组的长度基础上右移一位然后加上当前数组的长度相当于1.5倍,然后用新得到的长度和最小容量去对比

如果小于最小容量,则新容量为最小容量,反正则不变。然后新容量会和list最大长度对比,如果他比list最大值还大则返回默认定义的MAX_VALUE

最后调用copy方法进行赋值

本文初次读源码。。里面可能会有很多错误或者意思描述不清的地方,希望大家指出来,我好改正以免误导别人。。。大家一起共同学习进步

ArrayList底层实现的更多相关文章

  1. ArrayList底层原理

    ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...

  2. 模拟ArrayList底层实现

    package chengbaoDemo; import java.util.ArrayList; import java.util.Arrays; import comman.Human; /** ...

  3. ArrayList底层实现原理

    ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括null在内的所有元素.除了实现列表接口外,此类还提供一些方法来操作内部用来存储列表的数组 ...

  4. ArrayList 底层实现原理

    ArrayList的底层实现原理 1, 属性:private static final int DEFAULT_CAPACITY = 10; private static final Object [ ...

  5. JAVA SE ArrayList 底层实现

    Array 查询效率高,增删效率低( Link 增删效率高 Vector 线程安全 List 列表 源代码: package com.littlepage.test; /** * 基于底层实现Arra ...

  6. Java——ArrayList底层源码分析

    1.简介 ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔, 当数组大小不满足时需要增加存储能力,就要将已经有数 ...

  7. ArrayList底层代码解析笔记

    通过底层代码可以学习到很多东西: public class ArrayList<E> extends AbstractList<E> implements List<E& ...

  8. Java ArrayList底层实现原理源码详细分析Jdk8

    简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用 ...

  9. ArrayList、LinkedList、HashMap底层实现

    ArrayList 底层的实现就是一个数组(固定大小),当数组长度不够用的时候就会重新开辟一个新的数组,然后将原来的数据拷贝到新的数组内. LinkedList 底层是一个链表,是由java实现的一个 ...

随机推荐

  1. element-UI表格从一列中,拿到当前行的index----scope

    这里拿到每一行的index----------scope.$index 这里拿到每一行的数据-----------scope.row 转: https://blog.csdn.net/bright20 ...

  2. tabindex 属性

    tabindex 属性规定元素的 tab 键控制次序(当 tab 键用于导航时). 语法:<element tabindex="number">规定元素的 tab 键控 ...

  3. mtr语言真是逆天了

    实践证明,设计一个语言,还不是简单的解释没一行哦

  4. BLACKPYTHON学习(一)

    C/S结构了解 所谓的C/S就是客户端(client)和服务器端(server)的简称,也就是在基于这个的基础上编写相关的代码:一个就是客户端一个就是服务端. TCP(client) 客户端编写 #因 ...

  5. python应用:生成简单二维码

    概述 \(\quad\)第一篇python的应用就打算写一写用python生成简单的二维码啦.因为二维码在日常生活中越来越常用了,部分博客也用二维码来用作打赏的工具.但是要提醒大家的是,千万不要乱扫街 ...

  6. Cisco Packet Tracer中通过集线器组网

    Cisco Packet Tracer中可以通过集线器将多台电脑完成通信. Cisco Packet Tracer 6.2.0 一.添加三台电脑设备 1.按照下图1.2步骤操作,2步骤执行三次,拖拽P ...

  7. 【TestNG测试】TestNG、Maven、testng.xml构建测试工程

    创建一个maven工程 使用Idea创建maven工程 ​ 建立类似如上的工程结构,src/main/java,src/test/java,pom.xml,testng.xml,这里由于我们使用工程是 ...

  8. [持久更新] 剑指offer题目Python做题记录

    第一题 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路:先快速定位到 ...

  9. 反爬虫和抗DDOS攻击技术实践

    导语 企鹅媒体平台媒体名片页反爬虫技术实践,分布式网页爬虫技术.利用人工智能进行人机识别.图像识别码.频率访问控制.利用无头浏览器PhantomJS.Selenium 进行网页抓取等相关技术不在本文讨 ...

  10. 解读Python编程中的命名空间与作用域

    变量是拥有匹配对象的名字(标识符).命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典.一个Python表达式可以访问局部命名空间和全局命名空间里的变量.如果一个局部变量和一个全局 ...