Java源码阅读-List
来源:互联网 发布:软件测试高级工程师 编辑:程序博客网 时间:2024/06/17 01:09
Java容器类的完整分类如图:
其中java.util.List属于Collection的子类,继承关系为:
List作为一个接口提供了基本的集合操作:
int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); boolean equals(Object o); int hashCode(); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index); int indexOf(Object o); int lastIndexOf(Object o); ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); List<E> subList(int fromIndex, int toIndex);常用的ArrayList与LinkedList都是实现该接口,重写其中的方法
java.util.ArrayList的继承关系为:
ArrayList对象的本质为elementData数组,size记录数组元素数量
private transient Object[] elementData;private int size;注意这里elementData数组是transient的,但ArrayList对象仍然可以序列化和反序列化,是因为ArrayList重写了writeObject和readObject方法,在序列化与反序列化时会使用自己实现的方法来进行操作。
参数为泛型的构造方法
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
trimToSize方法
public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } }该方法是将数组缩小为size大小,因为数组每次增长都会申请多一些空间,该方法就是将预留的元素空间去掉,最小化ArrayList对象的存储空间,注意该方法中有一个参数modCount,该参数来源于AbstracList,记录了list对象的修改次数,由于ArrayList不是进程安全的,每次add,remove等操作时都会修改modCount,在使用迭代器遍历ArrayList对象时,迭代器会将modCount与expectedModCount进行比较,如果两数不想等则抛出异常(迭代器在创建时将modCount赋给expectedModCount)。
add方法
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }扩容后在数组中添加元素,其中扩容的实现如下:
private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }private void grow(int minCapacity) { // overflow-conscious code int 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); }private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }ArrayList在扩容前先判断原有空间是否为空,若原有空间为空(即ArrayList为空)则暂定扩容大小取DEFAULT_CAPACITY(10)与minCapacity的最大值
elementData数组现有大小不能满足扩容要求,则调用grow方法
在grow方法中,数组扩容机制为newCapacity = oldCapacity + (oldCapacity >> 1),oldCapacity >> 1为二进制移位,即除以2,默认扩容为原来的1.5倍
这样扩容后仍不能满足要求的情况下,指定扩容大小为minCapacity(即参数指定的大小),成功扩容后还要判断新容量大小是否大于MAX_ARRAY_SIZE (Integer.MAX_VALUE - 8),在大于的情况下调用hugeCapacity方法检查是否溢出,最大可运行的数组大小为Integer.MAX_VALUE,在Integer.MAX_VALUE 仍不满足要求的情况下应该使用其他存储方式。
to be continued...
0 0
- Java源码阅读-List
- STL源码阅读-list
- List源码阅读
- contiki源码阅读之list
- java源码阅读
- 怎样阅读JAVA源码
- 如何阅读Java源码
- 如何阅读JAVA源码
- 如何阅读Java源码
- java 数据结构. 源码阅读
- java源码阅读心得
- 如何阅读Java源码
- 如何阅读Java源码
- JAVA源码阅读--String
- java阅读源码工具
- Java源码阅读-StringBuffer
- Java源码阅读-HashMap
- Java源码阅读体会
- h5学习笔记: css布局案例练习
- Swift-->GCD,NSThread,NSBlockOperation多线程使用(主线程回调)
- Jquery学习笔记
- git命令行学习思路总结
- git 的分支体系命令汇总
- Java源码阅读-List
- nodejs 全局变量和方法,以及console使用
- vim 学习总结
- exports,module对象
- 《React-Native系列》21、 解决RN在Android下不支持gif问题
- nodejs中Buffer的创建和转换
- [leetcode] 201. Bitwise AND of Numbers Range
- nodejs中文件,目录的操作(1)
- 状态栏(UIStatus)的使用