JDK8集合类源码解析 - ArrayList
ArrayList主要要注意以下几点:
1构造方法
2添加add(E e)
3 获取 get(int index)
4 删除 remove(int index) , remove(Object o)
5 判断是否存在 contains(Object o)
6 遍历
======================================
底层采用数组实现。
1构造方法
有三个 分别是 指定数组大小;不指定(创建一个空的,添加元素的时候再扩容);从一个集合创建

这里顺便说下集合的继承关系
Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet
2添加add(E e)
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 先判断容量够不够
//添加到末尾
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) { //空就创建一个长度为10的数组
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //操作计数+1 用于在遍历的时候判断是否有添加或者删除操作
if (minCapacity - elementData.length > 0)
grow(minCapacity);//扩容
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//变成原来的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//如果新容量 MAX_ARRAY_SIZE还大 那么新容量就设置为Integer.MAX_VALUE
newCapacity = hugeCapacity(minCapacity);
//复制数据
elementData = Arrays.copyOf(elementData, newCapacity);
}
3 获取 get(int index)
public E get(int index) {
rangeCheck(index); //看数组是否越界
return elementData(index);
}
4 删除 remove(int index) , remove(Object o)
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);//从删除的元素到最后的元素全部前移
elementData[--size] = null; // 方便gc回收
return oldValue;
}
remove(Object o) 先遍历找到该元素,然后在删除 ,删除方法和上面的方法类似,需要移动数组(如果不是最后一个元素的话)
5 判断是否存在 contains(Object o)
//遍历 找到了就返回下标 不然返回 -1
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;
}
6遍历
int cursor; // 遍历标志位
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount; public boolean hasNext() {
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
注意两点: 1遍历的时候 如果要删除元素 要使用Iterator
2只有调用了next才能调用remove
最佳实践
1如果能够预知集合大小,创建的时候最好使用指定大小的构造函数,能够提高性能(没有了扩容)
2线程不安全,多线程环境建议使用CopyOnWriteArrayList
3遍历集合 如果要删除元素 要使用Iterator
4底层基于数值实现,增删慢 获取快(仅限于下标方式)
JDK8集合类源码解析 - ArrayList的更多相关文章
- JDK8集合类源码解析 - HashSet
HashSet 特点:不允许放入重复元素 查看源码,发现HashSet是基于HashMap来实现的,对HashMap做了一次“封装”. private transient HashMap<E,O ...
- JDK8集合类源码解析 - LinkedList
linkedList主要要注意以下几点: 1构造器 2 添加add(E e) 3 获取get(int index) 4 删除 remove(E e),remove(int index) 5 判断对象 ...
- JDK8集合类源码解析 - HashMap
java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap.Hashtable.LinkedHashMap和TreeMap HashMap ...
- Java集合类源码解析:Vector
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...
- Java集合类源码解析:HashMap (基于JDK1.8)
目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...
- Java集合类源码解析:ArrayList
目录 前言 源码解析 基本成员变量 添加元素 查询元素 修改元素 删除元素 为什么用 "transient" 修饰数组变量 总结 前言 今天学习一个Java集合类使用最多的类 Ar ...
- Java集合类源码解析:AbstractMap
目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口 ...
- Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap
声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...
- Java集合类源码解析:LinkedHashMap
前言 今天继续学习关于Map家族的另一个类 LinkedHashMap .先说明一下,LinkedHashMap 是继承于 HashMap 的,所以本文只针对 LinkedHashMap 的特性学习, ...
随机推荐
- Hibernate一对多单向关联和双向关联映射方法及其优缺点 (待续)
一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同.它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的同 ...
- Java 并发AQS
转载出处:http://www.cnblogs.com/waterystone/ 一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQu ...
- eclipse中没有tomcat小猫
安装了tomcat,按网上的说明也使用了tomcatPluginV331 配置文件,还是没有小猫,后来我发现,网上的tomcatPluginV331 针对eclipse 4.4版本,所以应该是插件的版 ...
- JAVA高精度模板
刚开始还坚持用C++写高精来着,后来发现JAVA写高精方便太多了,所以也来学习一下JAVA高精度的模板. 参考:https://www.cnblogs.com/imzscilovecode/p/883 ...
- 第四章 栈与队列(c3)栈应用:栈混洗
- Win7 访问win2008 远程桌面提示:您的凭证不工作
背景: win7 远程桌面连接 服务器 windows 2008 报错,“您的凭证不工作”,但是 xp 系统却可以正常连接. 解决方法: 1.在“运行” 中执行 secpol.msc-->进入本 ...
- DHCP server 冒充及DOS攻击处理方案
一.DHCP服务器在运维上存在的常见问题: 1. DHCP服务器冒充 在DHCP服务器和客户端之间没有认证机制,如果在DHCP server覆盖的网络上随意接入一个DHCP server,就有可能造成 ...
- [LeetCode_94] Binary Tree Inorder Traversal
题目链接 https://leetcode.com/problems/binary-tree-inorder-traversal/ 题意 二叉树的中序遍历 思路 中序遍历:即"左中右&quo ...
- jQuery与js对象互转
@参考文章 1 jQuery对象转js 亲测有效 var $v=$("#v"); //jQuery对象 ); //js对象 或 var $v =$("#v") ...
- iOS 打包方式
https://www.cnblogs.com/wengzilin/p/4601684.html