【JDK1.8集合】之ArrayList
ArrayList的特点有:存取有序,元素可以重复,可以存null值,因为底层是数组,所以查询快,增删相对慢,非线程安全。
先看成员属性:
//默认初始容量 private static final int DEFAULT_CAPACITY = 10; //被用于空实例的共享空数组实例 private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //存放元素的数组,数组的长度为List的size //当元素被添加的时候,List的容量会被扩充到 DEFAULT_CAPACITY(10) // 非private是为了方便嵌套类的访问 //transient 修饰,该属性不会序列化,ArrayList有自己的序列化方法 transient Object[] elementData; //size,List的大小 private int size;
构造函数:
//无参构造,对容器进行初始化赋值{}。 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //自定义容量的构造函数,必须大于等于0。 public ArrayList(int initialCapacity) { //如果大于0 if (initialCapacity > 0) { //对存元素的数组进行初始化 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //和无参构造一样,将存放元素的数组进行默认初始化{} this.elementData = EMPTY_ELEMENTDATA; } else { //小于0,抛异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //集合构造函数 public ArrayList(Collection<? extends E> c) { //将集合转换为数组,并赋值给元素容器 elementData = c.toArray(); if ((size = elementData.length) != 0) { // 如果不是空集合,检查是否成功转换为数组 if (elementData.getClass() != Object[].class) //如果转换不成功,直接copy elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 空集合, this.elementData = EMPTY_ELEMENTDATA; } }
添加指定元素:
//将元素添加到该List的末尾. public boolean add(E e) { //size为当前List大小 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { //如果是第一次添加元素 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //在DEFAULT_CAPACITY(10)和当前的size+1取一个最大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //记录结构性修改次数 modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //增加数组的容量,确保它至少能容纳指定的最小容量的元素量。 //minCapacity 期望的最小容量 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; //保证新容量不大于Integer.MAX_VALUE - 8 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); }
指定位置添加:
//将元素插入到List的指定位置 public void add(int index, E element) { //检查index,保证size>index>0。 rangeCheckForAdd(index); //如果容量不足,将进行扩容 ensureCapacityInternal(size + 1); // Increments modCount!! //将数组的元素从index开始后面的元素(size-index),统一后移一位。 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
添加指定集合:
//将新Collection(按照迭代器所返回的元素顺序)的所有元素添加到该List的尾部. //Collection为空将NullPointerException. public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount //将a[0--(numNew-1)] copy 到 elementData[size--(size+numNew-1)] System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } //添加指定集合到指定位置。 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount 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; }
删除指定元素:
// 删除List指定位置上的元素 public E remove(int index) { //确保size>=index rangeCheck(index); // modCount++; //记录指定索引上的元素,作为返回值 E oldValue = elementData(index); //计算出index后面元素前移一位的位置,准备copy int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //将数组最后一个元素设置为null,由GC清理 elementData[--size] = null; // clear to let GC do its work return oldValue; }
删除首次出现的指定元素:
//删除List中首次出现的指定元素(如果存在), //ArrayList可以存放重复元素。 public boolean remove(Object o) { //如果元素为null if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } //不为null } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //删除指定位置元素,跳过index参数的边界检查以及不返回任何值 private void fastRemove(int index) { modCount++; //计算出index后面元素前移一位的位置,准备copy int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //将数组最后一个元素设置为null,由GC清理 elementData[--size] = null; // clear to let GC do its work }
删除List中指定的集合:
//删除List中指定Collection(非空)里面的元素 public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) //判断容器中是否包含elementData[r]元素 if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }
删除指定边界的元素:
//删除指定边界的元素,包小不包大。 protected void removeRange(int fromIndex, int toIndex) { modCount++; //计算出index后面元素前移一位的位置,准备copy int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // GC处理 int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; }
1.8新增的remove方法:
//刪除所有滿足指定条件的元素 @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicate at this stage // will leave the collection unmodified int removeCount = 0; final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; }
ArrayList的get方法:
//获得指定位置的元素index<=size public E get(int index) { rangeCheck(index); return elementData(index); }
ArrayList的set方法:
//将指定位置的值替换为新值 public E set(int index, E element) { // rangeCheck(index); //记录指定位置上的元素,作为返回值 E oldValue = elementData(index); elementData[index] = element; return oldValue; }
查找元素方法:
//顺序查找,返回元素第一次出现的位置,如果元素不存在,则返回-1 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 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; }
如果有不对的地方欢迎指出。
知识的学习,要真诚与谦虚才不会有眼无珠,人生苦短,不能浪费时间做无用功。
人生学习最悲哀的不过是,因为无知傲慢错过真正的好东西,又因为无知贪婪在假东西上耗费生命。