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 的特性学习, ...
随机推荐
- 如何获得scala的帮助和退出
scala> :helpAll commands can be abbreviated, e.g., :he instead of :help.:edit <id>|<line ...
- 笔记-Python中逗号的作用
1.用,去掉额外的换行符
- hibernate 中,出现了错误 "node to traverse cannot be null!" 如何改正
这个错误基本上是因为hql语句写错了而造成的, 返回找hql输出一下发现, hql语句中间少了几个空格, 写成了String hql = "from"+className+&quo ...
- Math.random控制随机数范围
let minNum= parseInt(Math.random()*7) + 1 let maxNum= parseInt(Math.random()*83) + 1 生成7~83的随机整数
- fullCalendar插件基本使用
效果图 html代码,需要引入jquery,layui,fullCalendar <!DOCTYPE html> <html lang="en"> < ...
- c中堆栈的理解
一直对堆栈的使用以及全局变量.静态全局变量.局部变量.静态局部变量.初始化的全局变量.未初始化的全局变量.初始化的局部变量.未初始化的局部变量理解的不是很清楚,今天抽个时间来总结以下这方面的知识: 1 ...
- CSS3实现图片循环旋转
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- c#: 以模态窗口显示于其它进程窗体之前
产品之工具箱,需要工具以模态窗体,显示于主界面之上.记下代码点,以做备忘. 1.IWin32Window internal class Win32Window : IWin32Window { pub ...
- html 导出pdf
地址: https://developers.itextpdf.com/examples/xml-worker/html-lists 主方法: public string Generate(strin ...
- EF语句拦截器-匹配当前的Controller,Action,User
示例代码,ps:一切都能实现,关键是你尝试的方向,别把简单问题复杂化导致进入死胡同出不来. using Mobile360.Core.Interfaces; using Mobile360.Core. ...