Java----- ArrayList构造、add、remove、clear方法实现原理源码分析
来源:互联网 发布:php 监控 插件 编辑:程序博客网 时间:2024/06/05 03:07
一.ArrayList内部的实现方式
ArrayList内部是通过Object[]实现的。
二.源码分析:
(1).构造方法
public ArrayList() { array = EmptyArray.OBJECT; } public ArrayList(int capacity) { if (capacity < 0) { throw new IllegalArgumentException("capacity < 0: " + capacity); } array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]); } public ArrayList(Collection<? extends E> collection) { if (collection == null) { throw new NullPointerException("collection == null"); } Object[] a = collection.toArray(); if (a.getClass() != Object[].class) { Object[] newArray = new Object[a.length]; System.arraycopy(a, 0, newArray, 0, a.length); a = newArray; } array = a; size = a.length; }ArrayList有3个构造方法,先看第一个,array是一个成员变量,它是Object[]类型的,当我们在new一个空参的ArrayList的时候,系统默认调用了EmptyArray中的OBJECT属性,EmptyArray类具体实现如下:
public final class EmptyArray { private EmptyArray() {} public static final boolean[] BOOLEAN = new boolean[0]; public static final byte[] BYTE = new byte[0]; public static final char[] CHAR = new char[0]; public static final double[] DOUBLE = new double[0]; public static final int[] INT = new int[0]; public static final Class<?>[] CLASS = new Class[0]; public static final Object[] OBJECT = new Object[0]; public static final String[] STRING = new String[0]; public static final Throwable[] THROWABLE = new Throwable[0]; public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0]; public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0]; public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE = new java.lang.reflect.TypeVariable[0];}
从EmptyArray类中可知,当默认使用ArrayList空参的构造方法的时候,ArrayList内部会new Object[0]的空数组。再看ArrayList的第二个构造方法,先检验参数的有效性,当传入的参数小于0的时候,会抛出非法参数异常。如果参数合法,成员变量array的赋值,使用的是一个三元运算,当capacity == 0时,系统默认生成一个空数组,当capacity>0时,系统会生成一个长度为capacity的数组。最后看第三个构造方法,第一步对输入参数的合法性检验,若为空,则抛出空指针异常;第二步将输入集合转换成数组a;第三步判断当前数组a是否是Object[]类型,如果不是,创建一个Object类型的数组进行复制(复制方法使用System.arraycopy),再赋值给a;第四步将转换的数组a赋值给成员变量array;第五步将数组的长度赋值给成员变量size。(2).add()方法
/** * Adds the specified object at the end of this {@code ArrayList}. * * @param object * the object to add. * @return always true */ @Override public boolean add(E object) { Object[] a = array; int s = size; if (s == a.length) { Object[] newArray = new Object[s + (s < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : s >> 1)]; System.arraycopy(a, 0, newArray, 0, s); array = a = newArray; } a[s] = object; size = s + 1; modCount++; return true; }这里只分析简单的add()方法,第一步将数组,集合长度赋值给局部变量a和s;第二步判断集合的长度是否等于数组的长度,如果等于,需要重新分配数组和重新计算分配内存的空间大小。源码计算内存空间的大小,使用的是一个三元表达式,当集合的长度小于 MIN_CAPACITY_INCREMENT/2 时,系统会分配MIN_CAPACITY_INCREMENT各长度;当集合的长度大于 MIN_CAPACITY_INCREMENT/2 时,系统会分配当前长度的一半(s >>1表示当前长度右移一位,相当于s = s/2)。然后将数组的数据赋值到新的数组中,再更新原来数组。
private static final int MIN_CAPACITY_INCREMENT = 12;第三步将传入的Object对象添加到数组下标为s处;第四步将当前集合长度加1;第五步modCount自增,它主要是用来记录集合修改的次数(判断是否出现并发修改异常)。
(3).remove()方法
/** * Removes the object at the specified location from this list. * * @param index * the index of the object to remove. * @return the removed object. * @throws IndexOutOfBoundsException * when {@code location < 0 || location >= size()} */ @Override public E remove(int index) { /** * 1.局部变量赋值 */ Object[] a = array; int s = size;/** * 2.判断删除的下标是否超过了集合的长度,超过抛出越界异常 */ if (index >= s) { throwIndexOutOfBoundsException(index, s); } /** * 3.获取下标index的所对应的元素 */ @SuppressWarnings("unchecked") E result = (E) a[index]; /** * 4.将下标index后面的所有元素都向前移动一位 */ System.arraycopy(a, index + 1, a, index, --s - index); /** * 5.集合最后一位设置为空,防止内存泄露,因为删除了一个元素 */ a[s] = null; // Prevent memory leak /** * 6.集合长度重新赋值 */ size = s;/** * 7.记录修改次数 */ modCount++; return result; }
(4).clear()方法
/** * Removes all elements from this {@code ArrayList}, leaving it empty. * * @see #isEmpty * @see #size */ @Override public void clear() { /** * 判断集合大小是否不等于0 */ if (size != 0) { /** * 将数组的数据元素填充为null */ Arrays.fill(array, 0, size, null); /** * 集合长度设置为0 */ size = 0; /** * 记录修改次数 */ modCount++; } }
阅读全文
0 0
- Java----- ArrayList构造、add、remove、clear方法实现原理源码分析
- java中ArrayList源码方法理解--add(),remove()
- Java集合ArrayList实现原理——源码分析
- Java集合---ArrayList源码分析和实现原理
- JAVA ArrayList集合add(int index, E element)方法源码简单分析
- 源码分析-java-ArrayList-基本方法及实现
- 【Android】ArrayList通过remove方法删除元素对象源码分析
- ArrayList——ArrayList.add()源码分析
- ArrayList的add和remove方法
- Java源码:ArrayList的实现原理
- ArrayList的add(Object obj)和remove(Object obj)和remove(index)和get(index)的源码分析
- 小白学习之路(三):java ArrayList源码add操作和remove操作学习
- 节点定义,成员分析,构造方法和add方法实现
- 数据结构之解析ArrayList源码的add,remove,set,contains
- ArrayList和LinkedList add的源码分析
- Java ArrayList源码分析
- Java ArrayList 源码分析
- 《JAVA源码分析》:ArrayList
- Bruce force 普通模式匹配算法
- linux的一些命令
- 如何零基础学习Python?
- Intent 和 Intent 过滤器
- 低层视觉:使用多图像——从运动估计仿射模型
- Java----- ArrayList构造、add、remove、clear方法实现原理源码分析
- netcat的安装
- 26 设备树里mcp2515的描述
- Android JNI开发(8)--JNI出坑指南
- win10 2016 长期服务版的ISO文件中本身就带有KMS激活KEY
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
- 栈的压入和弹出
- 比特币学习之区块链
- 查看本地服务器MYSQL的端口号