源码分析(5)-ArrayList、Vector和LinkedList(JDK1.8)
一、概述
1、线程安全:ArrayList和LinkedList非线程安全的、Vector线程安全的。
2、底层数据结构:ArrayList和Vector底层数据结构是数组;LinkedList双向链表。
3、时间复杂度是否受插入和删除元素位置影响:ArrayList和Vector受影响,add(E e)方法时间复杂度O(1)和add(int index, E element)方法时间复杂度O(n-index);LinkedList受影响,add(E e)方法时间复杂度O(1)和add(int index, E element)方法时间复杂度O(n)。
4、是否支持随机访问:ArrayList和Vector支持;LinkedList不支持。
5、内存空间占用:ArrayList和Vector空间浪费主要体现在在list列表的结尾会预留一定的容量空间;LinkedList空间花费则体现在每一个元素都需要消耗更多的空间(因为要存放直接后继和直接前驱以及数据)。
二、集合UML类图
ArrayList和LinkedList继承和实现相同,LinkedList实现java.util.Deque<E>接口和继承java.util.AbstractSequentialList<E>抽象类。

三、ArrayList源码分析
1、重要成员变量
//数组,存储数据
transient Object[] elementData;
//数组长度
private int size;
//数组结构变更次数
protected transient int modCount = 0;
2、插入
//添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1);//确认容量足够
elementData[size++] = e;
return true;
} private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);//初始化容量10,返回初始容量和需要最小容量选择最大值
}
return 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;
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);//复制数组
}
//指定位置添加数组
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++;
}
3、删除
//删除元素
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);数组复制,index位置以后的元素前移1个位置
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
四、Vector源码分析
成员方法和ArrayList相似,不同之处在于方法都是synchronized同步锁修饰。
1、重要成员变量
//数组,存储数据和ArrayList相同
protected Object[] elementData;
//数组长度,等同于ArrayList的size
protected int elementCount;
//扩容量
protected int capacityIncrement;
2、插入
//添加元素
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);//确保容量
elementData[elementCount++] = e;//尾部添加元素
return true;
}
//
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);//扩容
}
//
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);//默认扩容2倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);//复制数组
}
五、LinkedList源码分析
1、重要成员变量
//双向链表节点长度
transient int size = 0;
//头结点
transient Node<E> first;
//尾结点
transient Node<E> last;
2、数据结构
private static class Node<E> {
E item;//数据
Node<E> next;//下一个节点
Node<E> prev;//前一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
3、插入
//插入到头部
public void addFirst(E e) {
linkFirst(e);
}
//
private void linkFirst(E e) {
final Node<E> f = first;//头结点
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)//头结点为空
last = newNode;
else
f.prev = newNode;//原头结点的前一个节点指向新节点
size++;
modCount++;
}
//尾部添加节点
public void addLast(E e) {
linkLast(e);
}
//
void linkLast(E e) {
final Node<E> l = last;//尾结点
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)//尾结点为空,此时头尾节点都是空
first = newNode;
else
l.next = newNode;//尾结点执行新节点
size++;
modCount++;
}
//插入节点默认在尾部添加
public boolean add(E e) {
linkLast(e);
return true;
}
//指定位置添加节点
public void add(int index, E element) {
checkPositionIndex(index); if (index == size)
linkLast(element);//尾部添加节点
else
linkBefore(element, node(index));
}
//
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
//
Node<E> node(int index) {
// assert isElementIndex(index); if (index < (size >> 1)) {//插入位置小于0.5*size,正向遍历
Node<E> x = first;
for (int i = 0; i < index; i++)//查询待插入位置节点
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)//逆向遍历
x = x.prev;
return x;
}
}
4、删除
//删除指定位置元素
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));//遍历查询index位置元素
}
//
E unlink(Node<E> x) {//删除数据
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev; if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
} if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
} x.item = null;
size--;
modCount++;
return element;
}
其他方法不再讲解。
源码分析(5)-ArrayList、Vector和LinkedList(JDK1.8)的更多相关文章
- 集合源码分析[3]-ArrayList 源码分析
历史文章: Collection 源码分析 AbstractList 源码分析 介绍 ArrayList是一个数组队列,相当于动态数组,与Java的数组对比,他的容量可以动态改变. 继承关系 Arra ...
- java读源码 之 list源码分析(ArrayList)---JDK1.8
java基础 之 list源码分析(ArrayList) ArrayList: 继承关系分析: public class ArrayList<E> extends AbstractList ...
- 【集合框架】JDK1.8源码分析之ArrayList详解(一)
[集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...
- 源码分析(2)-LinkedHashMap(JDK1.8)
1.概述 LinkedHashMap继承自HashMap:在HashMap基础上,通过维护一条双向链表,解决了HashMap键值对遍历顺序和插入顺序一致的问题. 想了解LinkedHashMap源码, ...
- 【集合框架】JDK1.8源码分析之ArrayList(六)
一.前言 分析了Map中主要的类之后,下面我们来分析Collection下面几种常见的类,如ArrayList.LinkedList.HashSet.TreeSet等.下面通过JDK源码来一起分析Ar ...
- Java集合源码分析之ArrayList
ArrayList简介 从上图可以看到,ArrayList是集合框架中List接口的一个实现类,它继承了AbstractList类,实现了List, RandomAccess, Cloneable, ...
- JDK源码学习笔记——ArrayList/Vector
一.类定义 public class ArrayList<E> extends AbstractList<E> implements List<E>, Random ...
- 源码分析(4)-ConcurrentHashMap(JDK1.8)
一.UML类图 ConcurrentHashMap键值不能为null:底层数据结构是数组+链表/红黑二叉树:采用CAS(比较并交换)和synchronized来保证并发安全. CAS文章:https: ...
- 源码分析(1)-HashMap(JDK1.8)
UML类图 java.util.Map<K, V>接口,有4个实现类:HashMap.Hashtable.LinkedHashMap和TreeMap. 1.说明 (1)HashMap除允许 ...
- 源码分析二(ArrayList与LinkedList的区别)
一:首先看一下ArrayList类的结构体系: public class ArrayList<E> extends AbstractList<E> implements Lis ...
随机推荐
- 什么是 Nginx?
Nginx (engine x) 是一款轻量级的 Web 服务器 .反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理? 反向代理(Reverse Proxy)方式是指以代理服 ...
- HBase Filter 过滤器之 ValueFilter 详解
前言:本文详细介绍了 HBase ValueFilter 过滤器 Java&Shell API 的使用,并贴出了相关示例代码以供参考.ValueFilter 基于列值进行过滤,在工作中涉及到需 ...
- Spark_Transformation和Action算子
Transformation 和 Action 常用算子 一.Transformation 1.1 map 1.2 filter 1.3 flatMap ...
- Rabbit的字符串 字符串最小表示法
Rabbit的字符串 #include<bits/stdc++.h> using namespace std; ; char s[maxn]; int get_min_pos() { , ...
- 自定义docker的镜像
- Power安装linux-BIG ENDIAN mysql编译安装
一.安装系统,不选择额外的软件 mkvdev -vadapter vhost0 -vdev hdisk2 -dev db_mysql01_sys mkvdev -vadapter vhost0 -vd ...
- maven打包相关配置
1.在pom.xml中进行如下配置: <build> <plugins> <plugin> <groupId>org.springframework.b ...
- CF894B Ralph And His Magic Field
题目链接:http://codeforces.com/contest/894/problem/B 题目大意: 往一个 \(n \times m\) 的网格中填数字 \((1 \le n,m \le 1 ...
- 基于java的雷电游戏
基于java的雷电游戏基本功能包括:敌方飞机随机飞行.我方飞机手动控制飞行,射击比拼,游戏闯关等.本系统结构如下: (1)雷电游戏状态调整功能: 在游戏启动时,游戏会自动进行初始化的验证. 若初始化成 ...
- java中的redis常用操作
https://blog.csdn.net/lixiaoxiong55/article/details/81592800 超详细版 常规操作 public class TestReidsComm ...