JAVA 集合类(java.util)源码阅读笔记------ArrayList
来源:互联网 发布:java finalize 异常吗 编辑:程序博客网 时间:2024/05/20 14:43
一、继承关系
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
继承自AbstractList抽象类,实现List接口,RandomAccess接口,Cloneable接口, java.io.Serializable接口。
说明:(1)RandomAccess:空接口,实现该接口代表该类拥有随机访问list对象的能力。
(2)Cloneable:空接口,实现该接口,重写Object的clone方法,否则会抛出异常。调用super.clone()实现对象的复制,如果对象中有引用,可以在super.clone后面进行处理。
(3)java.io.Serializable:空接口,实现该接口代表该类可序列化
类中的方法都是对List接口中方法的具体实现。
二、成员变量
private static final int DEFAULT_CAPACITY = 10;//默认的数组长度transient Object[] elementData;//存储list中元素的数组,transient关键字表示该对象在ArrayList序列化时不被序列化。private int size;//数组中实际元素的个数private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//数组的最大长度
三、重要方法说明
(1)clone: 保证复制ArrayList对象时,内部包含的elementData数组引用能重新申请空间创建数组,为深复制。
public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone();//保证该clone是深复制,不加这句话,则复制的ArrayList对象中elementData指向的还是原对象中的数组。 v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } }
(2)toArray:传入参数,将elementData中数据存入的数组。若该数组的长度<size,则重新返回一个复制了elementData数据的该类型数组;否则直接将elementData中元素向a中复制,同时将a[size()]置为空,返回a。
@SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
(3)add:当数组长度不够时,需要动态扩容
public boolean add(E e) { ensureCapacityInternal(size + 1); // size为element数组的实际大小,若size+1<elementData.length,则不用动态扩容,否则需要将elementData进行动态扩容。 elementData[size++] = e; return true; }private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_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); }grow:elementData数组扩容private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length;//每次增长newCapacity=oldCapacity*1.5,为原来的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1);//如果oldCapacity*1.5倍后,容量还是比minCapacity要小,则将newCapacity的值直接置为minCapacity if (newCapacity - minCapacity < 0) newCapacity = minCapacity;//如果增长的新长度大于了MAX_ARRAY_SIZE,则调用hugeCapacity来获取一个不大于Integer.MAX_VALUE的值。 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win://重新申请一个newCapacity长度的数组空间,并把elementData数组中内容拷贝过去。 elementData = Arrays.copyOf(elementData, newCapacity); }hugeCapacity: elementData的最大容量private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError();//当最小保证的容量minCapacity比MAX_ARRAY_SIZE还大时,返回Integer.MAX_VALUE;否则直接返回MAX_ARRAY_SIZE return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
(4) add:在指定位置add一个元素
public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // 确保数组的长度>=size+1//将elementData中index到数组最后一个元素,整体向后移动一个位置,空出index这一个位置,将element填入 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length;//确保数组能容下添加的所有元素,可能进行动态扩容 ensureCapacityInternal(size + numNew); // Increments modCount//计算从Index到处数组最后一个元素需要移动的元素的个数 int numMoved = size - index; if (numMoved > 0)//直接采用System.arraycopy将elementData数组中从index开始到最后一个元素位置这一段数据,移动到index+numNew位置 System.arraycopy(elementData, index, elementData, index + numNew, numMoved);//若index等于size,则直接在原数组后面添加 System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; }
(5)remove
//是一个前闭后开的区间,就是toIndex位置的元素不被移除,fromIndex位置元素被移除protected void removeRange(int fromIndex, int toIndex) { modCount++;//需要移动的元素的个数=toIndex到最后一个元素位置 int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null;//设置为null,让gc有机会回收 } size = newSize; }
(6)此外还提供了private void readObject(java.io.ObjectInputStream s)、 private void writeObject(java.io.ObjectOutputStream s)两个私有的序列化反序列化方法。
注意:
关于ArrayList中的Iterable(collection继承自此接口,所以collection的所有子类或者实现类都需要实现Iterator方法)接口中iterator()方法的实现
若一个线程在操作该ArrayList的iterator时,另一个线程对该ArrayList对象进行了添加修改删除更新操作,则会抛出new ConcurrentModificationException();
原因:http://www.cnblogs.com/skywang12345/p/3308762.html
关于ArrayList中的Iterable(collection继承自此接口,所以collection的所有子类或者实现类都需要实现Iterator方法)接口中iterator()方法的实现
若一个线程在操作该ArrayList的iterator时,另一个线程对该ArrayList对象进行了添加修改删除更新操作,则会抛出new ConcurrentModificationException();
原因:http://www.cnblogs.com/skywang12345/p/3308762.html
阅读全文
0 0
- JAVA 集合类(java.util)源码阅读笔记------ArrayList
- JAVA 集合类(java.util)源码阅读笔记------LinkedList
- JAVA 集合类(java.util)源码阅读笔记------WeakHashMap
- JAVA 集合类(java.util)源码阅读笔记------Vector
- JAVA 集合类(java.util)源码阅读笔记------Stack
- JAVA 集合类(java.util)源码阅读笔记------HashMap
- JAVA 集合类(java.util)源码阅读笔记------Hashtable
- 解析java.util集合类源码(ArrayList)
- java.util.ArrayList 源码
- java.util.Vector 和java.util.ArrayList都是集合类
- Java源码阅读-ArrayList
- Java源码阅读-ArrayList
- java.util.ArrayList源码解析
- java.util.ArrayList源码解析
- Java集合源码--ArrayList
- java类库的阅读笔记_jdk1.7.0_40_java.util.ArrayList
- Java集合类源码阅读
- java.util.concurrent 源码阅读
- Struts2标签
- 看懂三篇文章--需要归纳
- FCC-Object Oriented and Functional Programming
- 为什么要使用redis
- mapreduce 10020端口错误
- JAVA 集合类(java.util)源码阅读笔记------ArrayList
- Android 6.0 使用蓝牙BLE 时 报错:java.lang.SecurityException:Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOC
- linux常用操作
- 动态内存和智能指针
- Android-贪吃蛇(二)-自定义的view
- void和const使用技巧
- UiAutomatorHelper 调试类
- x264设置固定I帧问题
- define声明当中的#号使用