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 的特性学习, ...
随机推荐
- 第三篇:jmeter的作用域和执行顺序
1.元件的作用域: 8类可执行的元件,testplan和threadgroup不属于可执行的元件:这些元件中,取样器,是典型的不与其他元件发生交互作用的元件,逻辑控制器只对其子节点的取样器有效,而其他 ...
- metasploit framework(九):SMB服务扫描
SMB版本扫描 扫描命名管道,判断SMB服务类型 SMB共享枚举 SMB用户枚举 SID枚举
- 对象转化为json
google开发的Gson转换利器,String json = new Gson ().toJson(object); 一行代搞定. 别忘了引入jar包 转自:https://zhidao.baidu ...
- Win7下VB6.0不能加载mscomctl.ocx的解决办法
下载这个:http://pan.baidu.com/s/1sjJgrbJ 然后在命令框下注册这个组件: regsvr32 mscomctl.ocx 即可
- linux安装zookeeper及使用
一.安装条件 想要安装zookeeper,必须先在linux中安装好jdk.安装步骤见: https://www.cnblogs.com/expiator/p/9987351.html 二.下载并解压 ...
- centos7.2 +cloudstack 4.11 +KVM +ceph 安装配置(网卡带聚合)
系统安装,注意:管理节点版本是有要求的,配置为centos 7.2 最小安装版本(非最小化安装). 系统分区要求 /boot/efi 200MB / 100G /var 100G swap 0 其它给 ...
- 第四章 栈与队列(c3)栈应用:栈混洗
- Mac快捷键大全
Android Studio command+option+L:格式化代码 Visual Studio Code option+shift+f:格式化代码 先按command+k,再按command+ ...
- 微信小程序开发——小程序分享转发
关于小程序的转发: 最简单的就是点击小程序右上角菜单“转发”按钮直接分享,不过这种分享有点不太友好,实用性也不强. 当然,你可以自定义分享内容,包括标题,简介,图片及分享的小程序页面路径. 再高级一点 ...
- vcenter或workstation12导入ovf出错:硬件系列vmx 14不受支持
原因是因为导出ovf的虚拟机版本太高. 两个方法,一个强制,一个推荐. 强制 1. 打开ovf后缀文件,把<vssd:VirtualSystemType>vmx-14</vssd:V ...