public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList繼承自AbstractList,實現了List、RandomAccess、Cloneable、Serializable接口java
1.無參構造數組
/** * 第一種、調用ArrayList(10)默認初始化一個大小爲10的Object數組 (DEFAULTCAPACITY_EMPTY_ELEMENTDATA=10) */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
2.有參構造安全
/** *第二種 */ public ArrayList(int initialCapacity) { //若是用戶初始化大小小於0拋異常 //不然新建一個用戶初始值大小的Object數組 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
/** * 第三種、將容器數組化處理並將這個數組值賦給Object數組 */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { //當c.toArray返回的不是Object類型的數組時,進行下面轉化 if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 用空數組替換 this.elementData = EMPTY_ELEMENTDATA; } }
//第一步: public boolean add(E e) { ensureCapacityInternal(size + 1); 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++; // 若是添加元素後大於當前數組的長度,則進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //第四步:(擴容) private void grow(int minCapacity) { int oldCapacity = elementData.length; //將數組的長度增長原來數組的一半 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //若是擴充一半後仍然不夠,則newCapacity=minCapacity;(minCapacity實際元素的個數) if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
//第一步: public void add(int index, E element) { rangeCheckForAdd(index); //檢查index的值是否在0到size之間,能夠爲size。 ensureCapacityInternal(size + 1); //看elementData的長度是否足夠,不夠擴容 //將elementData從index開始後面的元素日後移一位 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //第二步:(多了判斷index是否超出範圍) private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //第三步: private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } //第四步:(判斷是否須要擴容) private void ensureExplicitCapacity(int minCapacity) { modCount++; // 若是添加元素後大於當前數組的長度,則進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //第五步:(擴容) private void grow(int minCapacity) { int oldCapacity = elementData.length; //將數組的長度增長原來數組的一半 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //若是擴充一半後仍然不夠,則newCapacity=minCapacity;(minCapacity實際元素的個數) if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
public E remove(int index) { //第一步:若是index>=size拋出異常 rangeCheck(index); modCount++; //第二步:獲取刪除元素的值 E oldValue = elementData(index); //第三步:將index後面全部元素往前移一位 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; //第四步:返回要刪除的元素 return oldValue; }
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; }
//第一步: public E set(int index, E element) { //檢查index是否小於size,若是不是拋異常 rangeCheck(index); E oldValue = elementData(index); //覆蓋ArrayList中index上的元素 elementData[index] = element; //返回被覆蓋的元素 return oldValue; } //第二步: private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
//第一步: public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } //第二步: static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); }
//1)修改次數加1 //2)強elementData中空餘的空間(包括null值)去除, //例如:數組長度爲10,其中只有前三個元素有值,其餘爲空,那麼調用該方法以後,數組長度變爲3 public void trimToSize() { //修改次數加1 modCount++; if (size < elementData.length) { elementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size); } }
public Object[] toArray() {return Arrays.copyOf(elementData, size);} //第一種方式(最經常使用) Integer[] integer=arrayList.toArray(new Integer[0]); //第二種方式(容易理解) Integer[] integer=new Integer[arrayList.size()]; arrayList.toArray(integer);
contains()多線程
public boolean contains(Object o) { return indexOf(o) >= 0; } 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 class Test01 { public static void main(String[] args) { List<String> list1=new ArrayList<>(); list1.add("A"); list1.add("B"); list1.add("C"); //第一種遍歷方式:迭代器 Iterator<String> iterator=list1.iterator(); while (iterator.hasNext()){ String result=iterator.next(); System.out.println(result); } //第二種遍歷方式:經過下標遍歷 for (int i = 0; i < list1.size(); i++) { String result=list1.get(0); System.out.println(result); } //第三種遍歷方式:for-each for (String a:list1) { System.out.println(a); } } }
第二種遍歷的效率是最高的。dom
三種方式時間差對比:源碼分析
package com.woniu.chapter23; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @Author: Aweicy * @Date: 2020/4/110:33 */ public class Test01 { public static void main(String[] args) { List<String> list1=new ArrayList<>(); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("A"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); list1.add("B"); list1.add("C"); Long time1=System.currentTimeMillis(); //第一種遍歷方式:迭代器 Iterator<String> iterator=list1.iterator(); while (iterator.hasNext()){ String result=iterator.next(); System.out.println(result); } Long time2=System.currentTimeMillis(); System.out.println(time2-time1); Long time3=System.currentTimeMillis(); //第二種遍歷方式:經過下標遍歷 for (int i = 0; i < list1.size(); i++) { String result=list1.get(0); System.out.println(result); } Long time4=System.currentTimeMillis(); System.out.println(time4-time3); Long time5=System.currentTimeMillis(); //第三種遍歷方式:for-each for (String a:list1) { System.out.println(a); } Long time6=System.currentTimeMillis(); System.out.println(time6-time5); } }
分析得出下面結論:性能
ArrayList整體來講比較簡單,不過ArrayList還有如下一些特色:this