1.ArrayList是一个相对来说比较简单的数据结构,最重要的一点就是它的自动扩容,可以认为就是我们常说的“动态数组”。
  来看一段简单的代码:

1
2
3
4
5
ArrayList<String> list = new ArrayList<String>();
list.add("语文: 99");
list.add("数学: 98");
list.add("英语: 100");
list.remove(0);

在执行这四条语句时,是这么变化的:

其中,add操作可以理解为直接将数组的内容置位,remove操作可以理解为删除index为0的节点,并将后面元素移到0处。

2. add函数

当我们在ArrayList中增加元素的时候,会使用add函数。他会将元素放到末尾。具体实现如下:

1
2
3
4
5
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}

我们可以看到他的实现其实最核心的内容就是ensureCapacityInternal。这个函数其实就是自动扩容机制的核心。我们依次来看一下他的具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_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);
} private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 扩展为原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果扩为1.5倍还不满足需求,直接扩为需求值
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);
}

也就是说,当增加数据的时候,如果ArrayList的大小已经不满足需求时,那么就将数组变为原长度的1.5倍,之后的操作就是把老的数组拷到新的数组里面。例如,默认的数组大小是10,也就是说当我们add10个元素之后,再进行一次add时,就会发生自动扩容,数组长度由10变为了15具体情况如下所示:

3 set和get函数

Array的put和get函数就比较简单了,先做index检查,然后执行赋值或访问操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
public E set(int index, E element) {
rangeCheck(index); E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
} public E get(int index) {
rangeCheck(index); return elementData(index);
}

4 remove函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public E remove(int index) {
rangeCheck(index); modCount++;
E oldValue = elementData(index); int numMoved = size - index - 1;
if (numMoved > 0)
// 把后面的往前移
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 把最后的置null
elementData[--size] = null; // clear to let GC do its work return oldValue;
}

注释很清楚:

Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

java ArrayList源码分析(转载)的更多相关文章

  1. Java - ArrayList源码分析

    java提高篇(二一)-----ArrayList 一.ArrayList概述 ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 nul ...

  2. Java ArrayList源码分析(有助于理解数据结构)

    arraylist源码分析 1.数组介绍 数组是数据结构中很基本的结构,很多编程语言都内置数组,类似于数据结构中的线性表 在java中当创建数组时会在内存中划分出一块连续的内存,然后当有数据进入的时候 ...

  3. Java ArrayList源码分析(含扩容机制等重点问题分析)

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

  4. Java|ArrayList源码分析|add()增加方法和grow()扩容方法

    本文结构: 1.介绍特点 2.基本方法 3.重点源码分析 1.介绍特点 ArrayList: 是List的一个具体实现子类,是List接口的一个数组实现 (里面必定维护了一个数组). 默认初始容量10 ...

  5. ArrayList源码分析超详细(转载)

    ArrayList源码分析超详细   ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要 ...

  6. Java集合源码分析(二)ArrayList

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

  7. Java集合源码分析(一)ArrayList

    前言 在前面的学习集合中只是介绍了集合的相关用法,我们想要更深入的去了解集合那就要通过我们去分析它的源码来了解它.希望对集合有一个更进一步的理解! 既然是看源码那我们要怎么看一个类的源码呢?这里我推荐 ...

  8. Java集合干货——ArrayList源码分析

    ArrayList源码分析 前言 在之前的文章中我们提到过ArrayList,ArrayList可以说是每一个学java的人使用最多最熟练的集合了,但是知其然不知其所以然.关于ArrayList的具体 ...

  9. java集合系列之ArrayList源码分析

    java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...

随机推荐

  1. echo常用操作

    echo -n 不换行输出 [root@C ~]# echo -n "peter" ; echo "linux" peterlinux echo -e 输出转义 ...

  2. Name Disambiguation in AMiner-Clustering, Maintenance, and Human in the Loop

    Name Disambiguation in AMiner: Clustering, Maintenance, and Human in the Loop paper:http://keg.cs.ts ...

  3. java中的逻辑运算符,以及&与&&的区别,|与||的区别

    原创,转载请留言联系 逻辑运算符: & 与 false&true=false:true&true=true:false&false=false 必须两个都是true才返 ...

  4. 5:django 常用函数

    用django写view函数的时候,我们常常用到django.shortcuts里面的很多常用函数, 这节我们来看看这些函数的具体用法吧 render render(request, template ...

  5. Java AQS学习

    参考原文: Java并发之AQS详解 <Java并发编程的艺术> AQS 概述 AQS简介 AQS(AbstractQueuedSynchronizer)就是一个抽象的队列同步器,它是用来 ...

  6. 按书上的例子,写了个长的go代码

    用于实现快速排序和冒泡排序的东东. 包括了蛮多东西的实现,输入输出,字符串处理等.... bubblesort.go package bubblesort func BubbleSort(values ...

  7. 四十四 常用内建模块 struct

    准确地讲,Python没有专门处理字节的数据类型.但由于str既是字符串,又可以表示字节,所以,字节数组=str.而在C语言中,我们可以很方便地用struct.union来处理字节,以及字节和int, ...

  8. Ubuntu18.04 安装Chrome浏览器

    一路copy paste就OK sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources. ...

  9. 洛谷P1955 [NOI2015] 程序自动分析 [并查集,离散化]

    题目传送门 题目描述 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或x ...

  10. cookies和session区别

    session原理:1.session是保存在服务器端,理论上是没有是没有限制,只要你的内存够大   2.浏览器第一次访问服务器时会创建一个session对象并返回一个JSESSIONID=ID的值, ...