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. GPUImage每个类的作用

    28 #import "GPUImageBrightnessFilter.h"                //亮度 29 #import "GPUImageExpos ...

  2. 静态成员变量和静态成员函数(static)

    数据成员可以分静态变量.非静态变量两种. 静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配 ...

  3. 提高你的Python编码效率的“武林秘籍”

    我用Python编程有几年了, 并且我仍然经常惊讶于Python代码可以如何的简洁,如何的 DRY . 我学到了很多小贴士和技巧,大多数来自于阅读开源项目的源代码,像Django, Flask, Re ...

  4. 浅谈MVC Razor基本语法

    首先说下MVC,mvc已经不用ViewState来保留网页的状态,所以大部分依赖ViewState的功能都将无法使用, 比如gridview的分页与排序,page trace等利用viewstate记 ...

  5. .net 分布式学习计划

    一: 1:.net分布式系统架构的思路     https://blog.csdn.net/slowlifes/article/details/53162014 2: nginx+iis实现负载均衡 ...

  6. 16节实用性爆棚的Ps课:零基础秒上手,让你省钱也赚钱

    ps视频教程,ps自学视频教程.ps免费视频教程下载,16节实用性爆棚的Ps课教程视频内容较大,分为俩部分: 16节实用性爆棚的Ps课第一部分:百度网盘,https://pan.baidu.com/s ...

  7. MySQL ZIP Archive 5.7.17 安装方法

    1.下载 2.解压缩 3.创建/修改配置文件 在MySQL安装目录下,新建my.ini,内容如下参考 [mysql] # 设置mysql客户端默认字符集 default-character-set=u ...

  8. PHPCMS 栏目添加字段和修改描述textarea变成fceditor编辑器

    一.添加字段方法: 1. 添加数据库字段:description1,添加位置:v9_catetory表 找到phpcms/moudles/admin/templates/category_add.tp ...

  9. CHAPTER 40 Science in Our Digital Age 第40章 我们数字时代的科学

    CHAPTER 40 Science in Our Digital Age 第40章 我们数字时代的科学 The next time you switch on your computer, you ...

  10. XAMPP安装PHP_GMP

    CentOS 6.4 Xampp 7.1.12 下载PHP7.1.12的源码包 yum install gmp-devel yum install m4 .tar.xz cd /root/php-/e ...