ArrayList实现
Posted 菜菜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList实现相关的知识,希望对你有一定的参考价值。
数组实现
父类:AbstractList
接口:List,RandomAccess,Cloneable,Serializable
字段:
//默认容量
private static final int DEFAULT_CAPACITY = 10;
//空的数组,构造函数参数为0和trim中使用,构造参数给0的人绝对会被打死,每放一个元素,就要重新copy一次
private static final Object[] EMPTY_ELEMENTDATA = {};
//实际保存数组,transient,这个字段不用写入流
transient Object[] elementData
//实际元素数目
private int size;
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //注意初始容量为0时给的对象,EMPTY_ELEMENTDATA this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } public ArrayList() { //默认构造函数 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c) { //转入的集合转换为数组 elementData = c.toArray(); //改变自己的size if ((size = elementData.length) != 0) { //这里有个坑,可能不能正确的返回Object[] Class对象,不能的话复制 // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } } //截断,在原数组上移动 public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } //比较关心的几个方法,存放,取出,查找 //查找,运行时间上界O(n),从这里也可用看出是允许放null 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; } //反向查找 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; } //返回index位置的元素 E elementData(int index) { return (E) elementData[index]; } //获取对应位置元素,O(1) public E get(int index) { //检查size,并没有判断小于0 rangeCheck(index); return elementData(index); } //将元素放在对应位置,index<size,list当成数组使用,注意,这样的代码会报错 //List<String> list = new ArrayList<>(100); // list.set(10, "123"); //根据构造函数可以知道,已经开辟了100长度的数组,但是就是不让你用 public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //原来的1.5备长度 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 elementData = Arrays.copyOf(elementData, newCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code //1-0,进入if,进行内存复制,开辟新的数组 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void ensureCapacityInternal(int minCapacity) { //构造函数给0,这里是false if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //ensureExplicitCapacity(1); ensureExplicitCapacity(minCapacity); } //增加一个元素 public boolean add(E e) { //为什么构造函数给0会被打死,看下面这个函数,一来就要新数组,新的数组长度也只有1 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } //元素放到index位置,0<=index<size public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //移除 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; // clear to let GC do its work return oldValue; } //O(n)的移除,注意在fastRemove方法里面也会出现内存复制 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; } //为什么elementData不用置null,方便重用 public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } //浅克隆 public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); 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); } } //返回副本 public Object[] toArray() { return Arrays.copyOf(elementData, size); } 结尾附上一个内存分布的代码,有指针真好 int main(int argc, char* argv[]) { //int ba[4]; int a[] = { 1, 2, 3, 4 }; int c = 5; int d = 6; int dd = 7; cout << a << endl; cout << a[-1] << endl; cout << a-1 << endl; cout<<&dd<<endl; cout << &d << endl; cout << &c << endl; //memcpy(ba, a, sizeof(int) * 4); //cout << ba[0] << endl; //cout << ba[1] << endl; return 0; }
以上是关于ArrayList实现的主要内容,如果未能解决你的问题,请参考以下文章