版本 jdk-7u71-windows-x64
JavaSE7 ArrayList源码下:http://flyouwith.iteye.com/blog/2171047
/** * 看下面这几个私有属性,就知道ArrayList实际上就是一个数组 * 其(数组、ArrayList)数据结构就是一个简单的线性序列 */ public class ArrayList<E> extends AbstractList<E> //这个 extends AbstractCollection<E> implements List<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; /** * 默认初始容量. */ private static final int DEFAULT_CAPACITY = 10; /** * 空数组 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 数组elementData 存储ArrayList的所有数据 */ private transient Object[] elementData; /** * size<=elementData.length,两者没什么特别关系 * size是数组elementData中元素(E) 的个数 */ private int size; /** * 构造方法1 * 构造一个与指定初始容量的空列表. * 例:ArrayList<E> array = new ArrayList<E>(10000); * 这时候size=0,但是数组的容量是10000 */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); this.elementData = new Object[initialCapacity]; } /** * 构造方法2 * api:构造一个空列表的初始容量10 * 我就不明白了,那里初始化容量大小了?、???? * 明明是构造一个容量是0的数组 */ public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } /** * 构造方法3 * 可以放一个实现Collection接口的集合进去set、list */ public ArrayList(Collection<? extends E> c) { // 1.将集合转换成数组,elementData指向这个数组 elementData = c.toArray(); // 2.设置size值 size = elementData.length; // 3.判断ele..是不是Object数组,不是的话创建一个,将内容(基本类型的值,对象的引用)copy进新数组中,返回 if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
下面看一下,构造方法3中的第一步(假设传进来的是一个ArrayList)和第三步。
/** * ArrayList实现的 Collection接口中toArray()方法 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } /** * 在Arrays类中找到的copyOf的方法 */ public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } /** * 直接看这个吧,上面构造方法3的第三步调用的也是这个方法 */ public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { //根据给定的paramClass数组类型,生成一个大小newLength的新数组 T[] copy = //三目运算 ((Object)newType == (Object)Object[].class) //构造方法3的第三步走的这里 ? (T[]) new Object[newLength] //Array.newInstance 是native的,看不到了 : (T[]) Array.newInstance(newType.getComponentType(), newLength); //这个也是 native方法,x = Math.min(original.length, newLength) //复制original[0~x]内容到copy[0~x]中,用这个操作数组还是很爽的 System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength)); return copy; }
其实一般的构造方法3,第三步都会走。
ArrayList<String> array = new ArrayList<String>(Arrays.asList("a","b")); //对应构造方法3的第一步 Object[] elementData = Arrays.asList("a","b").toArray(); System.err.println(elementData.getClass());//输出class [Ljava.lang.String;
下面继续源码:对数组进行扩容
/** * 给数组瘦身,释放资源,确定数组大小不会改变时用这个. * 生成一个新数组容量与元素个数一样 */ public void trimToSize() { //记录对arrayList的操作次数? 源码下再介绍 modCount++; if (size < elementData.length) { //上面介绍过了 elementData = Arrays.copyOf(elementData, size); } } /** * 手动给数组扩容,生成一个容量不小于paramInt数组,然后将内容copy进去 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; if (minCapacity - elementData.length > 0) // 给定数值不能比当前数组容量小: 执行 grow(minCapacity); } /** * 数组分配的最大大小,超过的话取Integer.MAX_VALUE */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 执行扩容 */ private void grow(int minCapacity) { int oldCapacity = elementData.length; //自己会根据当前容量算出一个扩容值,跟给定值比较选择最大的 //移位操作符>> 参考:http://flyouwith.iteye.com/blog/2163032 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //限定数组最大的容量 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); //继续copy 到一个新数组中 elementData = Arrays.copyOf(elementData, newCapacity); } /** * 限定数组最大容量不能超过Integer.MAX_VALUE=2147483647 */ private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
下面内容是一些基本方法
/** * 返回此列表的元素数量。 */ public int size() { return size; } /** * 是否只有一副皮囊 . */ public boolean isEmpty() { return size == 0; } /** * 是否包含指定o */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * 返回在数组中第一次出现的位置,没有找到返回-1 * 通过对象的equals比较 */ 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; } /** * 返回在数组中最后一次出现的位置,没有找到返回-1 * 从后面开始循环 * 通过对象的equals比较 */ public int lastIndexOf(Object o) { if (o == null) { for (int i = size - 1; i >= 0; i--) if (elementData[i] == null) return i; } else { for (int i = size - 1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } /** * 返回一个浅拷贝的ArrayList实例。(元素 * 本身并不是复制。) * 数组存基本类型的值,对象的引用。 * 所以copy的不过是引用,都指向一个对 */ public Object clone() { try { @SuppressWarnings("unchecked") ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { throw new InternalError(); } } /** * 返回一个数组,其中包含所有的元素在这个列表中 * 顺序(从第一个到最后一个元素)。 * 对象copy引用 * 该方法基于数组的和基于集合的api之间充当桥梁。 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } /** * 新建一个数组,放到这里拷贝ArrayList中内容 */ @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { //如果给定数组容量小于size ,则生成一个大小是size的数组,然后把内容copy进去 if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); //否则直接copy,上面有介绍这个方法的含义 System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } // 返回数组指定位置的元素 @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } /** * 返回在该列表中指定位置的元素 */ public E get(int index) { rangeCheck(index);//检核是否越界 return elementData(index); } /** *替换指定位置的元素,返回被替换元素 */ public E set(int index, E element) { rangeCheck(index);//检核是否越界 E oldValue = elementData(index); elementData[index] = element; return oldValue; } /** * 在末尾添加元素。. * 第一步上面有介绍这个方法。是否需要扩容 * 注意:size加1 */ public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } /** * 指定位置添加元素,从指定位置开始后面元素统一后移一位 . * 这里不是用的for循环来移位,而是copy,即使这样也比LinkedList慢好多 * 这个如果用for循环的话时间复杂度是O(this.size - index) copy应该是比这小的 * 但是肯定比LinkedList 的O(1) 要大的多 * 注意:size加1 */ public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1);//检核是否越界 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } /** * 跟上面性质是一样的。把删除位置后面的元素统一向前移动一位 * 比LinkedList慢 * 注意:size减1 */ 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; return oldValue; } /** * 删除第一次出现的指定元素从这个列表 * 通过for循环查找元素 */ 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; } /* * 私人去除方法,跳过范围检查和不返回 * 值删除 */ 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; } /** * 清空,通过for循环 */ public void clear() { modCount++; for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } /** * 添加一个集合到当前集合后面 * 先把要添加的集合转变成数组,然后对this数组扩容,copy到this数组中 * 比LinkedList慢 */ public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 扩容 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } /** * 在指定位置插入集合. * 先进行扩容,然后移位,之后把内容copy进来 */ public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 扩容 int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } /** * 这是protected的不能用。。 * remove区间的内容 * 先把fromIndex后的内容copy到toIndex后面 * 然后把后面toIndex-fromIndex个数的元素清空 */ protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); int newSize = size - (toIndex - fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; } /** * 检核越界 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 检核越界 */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 异常信息 . */ private String outOfBoundsMsg(int index) { return "Index: " + index + ", Size: " + size; }
相关推荐
ArrayList是Java集合框架中的一员,它是List接口的一个实现,提供了动态数组的功能。ArrayList的主要特点是它在内存中以数组的形式存储元素,因此对于随机访问元素,它的性能非常高效。本篇文章将深入探讨ArrayList...
通过以上对ArrayList源码的分析,可以总结出如下关键知识点: 1. ArrayList的实现基于动态数组,可以动态地进行容量的调整; 2. ArrayList具有默认初始化容量10,以及无参构造时延迟初始化的特性; 3. ArrayList...
ArrayList是Java编程语言中最常用的集合...总之,这个“ArrayList源码.zip”文件是Java程序员学习和优化代码的宝贵资源,它揭示了ArrayList内部的工作机制,帮助我们提升编程技巧,更好地理解和利用这个强大的集合类。
Java中ArrayList类的源码解析 ArrayList是Java中最常用的集合类之一,它实现了List接口,继承自AbstractList抽象类。在ArrayList中,我们可以看到它的源码实现了Iterable接口、List接口和Collection接口。下面我们...
### ArrayList源码解析(JDK 1.8) #### 概述 `ArrayList`是Java集合框架中的一个核心组件,它提供了动态数组的功能。与固定大小的数组不同,`ArrayList`可以随着元素的增加而自动扩展其容量。在JDK 1.8中,`...
JDK8的ArrayList源码文件
综上所述,Java源码大全是一个全面的Java学习资源,无论你是初学者还是有经验的开发者,都能从中找到有价值的代码示例和学习素材。通过这个压缩包,你可以系统地学习Java语言,掌握各种编程技巧,以及提升算法设计和...
2. **验证源码可见性**:返回IDE的项目视图,尝试打开某个Java类,如`String`或`ArrayList`。如果一切设置正确,IDE应能成功加载并显示对应类的源代码。 #### 扩展知识点 - **JRE与JDK的区别**:JRE(Java Runtime...
本资源根据个人学习和总结,主要介绍Java中ArrayList扩容机制源码的解析,主要包含文字和代码等内容,以源码的形式进行分析,详细介绍了ArrayList扩容机制的整个流程,特此将该资源分享
`java.util`包下的`List`、`Set`、`Map`等接口以及它们的实现类,如`ArrayList`、`HashMap`等,构成了Java集合框架。源码解析可以帮助我们理解这些数据结构的内部实现,优化数据存储和操作。 8. **网络编程** `...
其次,集合框架部分的源码将展示ArrayList、LinkedList、HashSet、HashMap等各种容器的使用方法,以及泛型、迭代器和比较器的概念。这部分代码可以帮助你理解Java集合的强大功能和灵活性。 再者,多线程编程的源码...
7. **集合框架**:Java集合框架包括数组、列表、队列、映射等数据结构,如`ArrayList`、`HashMap`等。源码揭示了这些数据结构的实现细节,对于优化和定制自己的数据结构非常有用。 8. **IO/NIO**:`java.io`和`java...
4. **集合框架**:Java集合框架包括List、Set、Map等接口及其实现类,如ArrayList、HashSet、HashMap等。源码分析能帮助理解它们的工作机制和性能特点,选择合适的数据结构存储和操作数据。 5. **多线程编程**:...
Java编程中ArrayList源码分析 Java编程中ArrayList源码分析是Java编程中一个重要的知识点,对于Java开发者来说,了解ArrayList的源码可以帮助他们更好地理解Java集合框架的实现机制,从而提高自己的编程水平。 ...
《深入剖析Java集合框架ArrayList源码》 Java集合框架中的ArrayList是开发者常用的数据结构,它是一种基于动态数组实现的列表。ArrayList的特点在于它的内部结构、性能优化以及在并发环境下的处理方式。本文将深入...
4. **集合框架**:Java集合框架是用于存储和操作对象的工具,包括List(如ArrayList、LinkedList)、Set(如HashSet、TreeSet)和Map(如HashMap、TreeMap)。源码可能包含各种数据结构的实现和操作,比如查找、排序...
《Java集合框架(2-9)-Collection - ArrayList 源码解析》 ArrayList是Java集合框架中的一个重要组件,它属于List接口的实现类,提供了一种动态数组的逻辑视图。ArrayList以高效、灵活的方式存储和操作对象序列,是...
第二章 ArrayList源码解析 ArrayList是Java集合框架中的一种动态数组,它继承自AbstractList,并实现了List接口。ArrayList主要用于存储可变大小的对象列表,它的核心是通过一个Object类型的数组elementData来实现...
此外,还会使用到Java集合框架中的数组和ArrayList来存储游戏元素。 2. **图形用户界面(GUI)**:游戏的界面通常是使用Java的Swing或JavaFX库来创建的。Swing提供了诸如JFrame、JPanel、JButton等组件,用于构建...