java的ArrayList分析
源码分析
具体关系:
我们平时常用需要掌握的:
ArrayList,LinkedList,HashMap,HashSet。。。List,Set,Map对比
接口 | 子接口 | 是否有序 | 是否允许元素重复 |
---|---|---|---|
Collection | 否 | ||
List | ArrayList | 否 | 是 |
LinkedList | 否 | 是 | |
Vector | 否 | 是 | |
Set | AbstractSet | 否 | 否 |
HashSet | 否 | 否 | |
TreeSet | 是(用二叉排序树) | 否 | |
Map | AbstractMap | 否 | 使用key-value来映射和存储数据,key必须唯一,value可以重复 |
HashMap | 否 | ||
TreeMap | 是(用二叉排序树) | 使用key-value来映射和存储数据,key必须唯一,value可以重复 |
ArrayList详解
内部主要是数组实现
1. 内部变量
/*** 初始化容量*/private static final int DEFAULT_CAPACITY = 10;/*** 用于空实例的共享空数组实例*/private static final Object[] EMPTY_ELEMENTDATA = {};/*** 共享的空数组实例,用于默认大小的空实例。我们将其与EMPTY_ELEMENTDATA区别开来,以了解添加第一个元素时需要充气多少。*/private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/*** 存储ArrayList的元素的数组缓冲区。 ArrayList的容量是此数组缓冲区的长度。添加第一个元素时,任何具有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空ArrayList将被扩展为DEFAULT_CAPACITY。*/transient Object[] elementData; // non-private to simplify nested class access/*** ArrayList的大小(它包含的元素数)** @serial*/private int size;
2. 构造函数
// 构造一个具有指定初始容量的空列表。
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}// 构造一个初始容量为10的空列表
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}// 构造一个包含指定*集合的元素的列表,其顺序由集合的迭代器返回。
public ArrayList(Collection<? extends E> c) {Object[] a = c.toArray();if ((size = a.length) != 0) {if (c.getClass() == ArrayList.class) {elementData = a;} else {elementData = Arrays.copyOf(a, size, Object[].class);}} else {// replace with empty array.elementData = EMPTY_ELEMENTDATA;}}
3. add 方法
// 将指定的元素追加到此列表的末尾。
public boolean add(E e) {ensureCapacityInternal(size + 1); // 增加modCount!elementData[size++] = e;return true;}/ **
* 在列表中特定的位置新增特定的元素,移动当前在该位置的元素(如果有)并且右边的任何后续元素(将其索引添加一个)
*/
public void add(int index, E element) {rangeCheckForAdd(index); // 判断ensureCapacityInternal(size + 1); // 增加modCount!System.arraycopy(elementData, index, elementData, index + 1, size - index);elementData[index] = element;size++;}// add和addAll使用的rangeCheck版本private void rangeCheckForAdd(int index) {if (index > size || index < 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// 增加容量以确保它至少可以容纳最小容量参数指定的元素数。
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);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在添加元素的时候,首先进行的是范围检查,防止其传入的参数小于0或者超过数组的size大小,再是和默认分配的大小值进行比较,如果大于默认大小就要进行扩容。扩容的时候首先把旧数组的大小提升1.5倍,成为新数组的大小值。同时也可以看到Arrylist的大小边界是Interger的最大值,这个数字是很大的:2147483647,也就是它的最大值是这么多,这个值足以我们程序员平常进行使用!在检查完毕和扩容完毕之后,就是要进行数组的拷贝了,我们开看一下System.arrayCopy()方法的源码:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
中可以看出,它是native修饰的,也就是说它是一个引用本地其他语言的代码库(windows就是.dll库)的方法,具体的源码我们不深究了,这里解释一下它的参数,src:你要从哪个数组复制,srcpos:要复制的位置起点 dest:要复制要哪个数组,destPos:要复制到的数组起始位置 lengh:复制的长度
System.arraycopy(elementData, index, elementData, index + 1, size - index);
4. remove方法
我们看romove方法首先还是进行范围检查,然后用elementData()方法去找到指定数组元素中的值,再用size-index-1转为numMoved,接着进行再次自我复制。然后把size-1甚至设置为null。这样这个数组中元素就是null了。
public E remove(int index) {//根据指定位置移除元素rangeCheck(index);//范围检查modCount++;//修改次数+1E oldValue = elementData(index);//根据数组元素的位置找到旧值int numMoved = size - index - 1;if (numMoved > 0)//判断是否大于0System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // return oldValue;//返回旧值}// 从此列表中删除第一次出现的指定元素,如果存在,则将其删除。如果列表不包含该元素,则不变。
public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}} else {for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;}// 专用remove方法,跳过边界检查,并且不返回删除的值。
private void fastRemove(int index) {modCount++;int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null; // clear to let GC do its work}
java的ArrayList分析相关推荐
- Java 集合 —— ArrayList 分析
List 集合的特征: 有序 可以重复 可以随机访问(使用下标 添加,删除,访问) ArrayList 是 List 的实现类,所以 ArrayList 具有 List 的特征 ArrayList 是 ...
- 【Java源码分析】LinkedList源码分析
类的定义如下 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E ...
- (转)性能分析之-- JAVA Thread Dump 分析综述
原文链接:http://blog.csdn.net/rachel_luo/article/details/8920596 最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相 ...
- Java针对ArrayList自定义排序的2种实现方法
这篇文章主要介绍了Java针对ArrayList自定义排序的2种实现方法,结合实例形式总结分析了Java操作ArrayList自定义排序的原理与相关实现技巧,下面就和动力节点java学院小编一起来看看 ...
- java内存溢出分析工具:jmap使用实战
java内存溢出分析工具:jmap使用实战 在一次解决系统tomcat老是内存撑到头,然后崩溃的问题时,使用到了jmap. 1 使用命令 在环境是linux+jdk1.5以上,这个工具是自带的,路 ...
- Java知识点总结(Java容器-ArrayList)
Java知识点总结(Java容器-ArrayList) @(Java知识点总结)[Java, Java容器, JavaCollection, JavaList] ArrayList 底层实现是数组,访 ...
- Java API —— ArrayList类 Vector类 LinkList类
1.ArrayList类 1)ArrayList类概述 · 底层数据结构是数组,查询快,增删慢 · 线程不安全,效率高 2)ArrayList案例 · 存储字符串并遍历 · 存储自定义对象并遍历 2. ...
- eclipse无法创建java虚拟机_手把手:Java内存泄漏分析Memory Analyzer Tool
点击上方"IT牧场",选择"设为星标"点击上方"IT牧场",选择"设为星标"技术干货每日送达 阅读文本大概需要3分钟. ...
- Java中ArrayList的练习
练习1:存储随机数 题目: 生成6个1~44之间的随机整数,添加到集合,并遍历集合. 思路: 1.需要存储6个数字,创建一个集合, 2.产生随机数,需要用到Random 3.用循环6次,来产生6个随机 ...
- java分析内存泄露工具_Eclipse Memory Analyzer(Java内存泄漏分析工具)
概述 一个大型的Java项目也许从开发到测试结束并未发现一些大的问题,但是在生产环境中还是会出现一些非常棘手的问题,如内存泄漏,遇到这样的问题对于一个经验尚浅的开发人员来说难度非常大,好的一点是JVM ...
最新文章
- 华为P30Pro国外采用4根天线设计,为何国内却只有2根?
- 【PAT乙级】1036 跟奥巴马一起编程 (15 分)
- kFreeBSD有活过来的迹象?UbuntuBSD
- linux 显示器分辨率设置太小了,显示器不显示 如何在设置回来,当“显示设置”中的分辨率不可用时,如何使用xrandr设置自定义分辨率...
- 正则匹配中文 UTF-8 GBK
- 计算机网络聚合怎么设置,交换机的端口聚合如何配置
- endnote修改正文中参考文献标注_如何用Endnote在论文中插入参考文献
- 机器学习、深度学习概念术语的理解
- VB编辑器之代码颜色修改
- Ubuntu:back up whole system
- [工具推荐] IPv4 和 IPv6 网站测速工具
- Git 初接触 (四) Git的分支操作
- 搜狗输入法弹出搜狗新闻的解决办法
- Only the Paranoid Survive
- OA系统以项目管理为中心,为会计事务所打造内外协同一体化平台
- 大数据相关书籍(包含Java, Scala, R, Linux, Spark, Hadoop, Hive, Hbase, Sqoop, Flume, Strom)
- 筹码分布的计算方法笔记
- springboot实现几种常见登录(注册)方式
- C++ 如何加载lib
- RabbitMQ的简单使用