特性   实现了三个标记接口: RandomAccess, Cloneable, java.io.Serializable 
public  class  ArrayList <E > extends  AbstractList <E >        implements  List <E >, RandomAccess , Cloneable , java .io .Serializable  
 
RandomAccess    支持随机访问(基于下标),为了能够更好地判断集合是ArrayList还是LinkedList,从而能够更好选择更优的遍历方式,提高性能! 
Cloneable    支持拷贝:实现Cloneable接口,重写clone方法、方法内容默认调用父类的clone方法。  1.浅拷贝    对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝 
public  Object clone ()  throws  CloneNotSupportedException  {               Study study = (Study) super .clone();                return  study; } 
 
2.深拷贝    对基本数据类型进行值传递,对引用数据类型创建一个新的对象,并复制内容,这是深拷贝 
public  Object clone ()  throws  CloneNotSupportedException  {    Study s = (Study) super .clone();     s.setScore(this .score.clone());     return  s; } 
 
 java的传参有基本类型和引用类型传参,参数传递时拷贝的都是栈中的内容。此处大概分为三种情况 
1.基本类型,存储在栈中所以拷贝的就是真实的值,修改后不影响原值 2.引用类型:栈中内容为对象引用,拷贝的也为引用 修改改变的是引用所指向的对象,由于引用的同一个对象,所以元对象改变了 3.String:虽然String也是引用类型 但于String是不可变对象 在修改时会讲引用指向一个新的对象,所已他们的引用变得不同了,当然不会改变原值
Serializable 序列化:将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据,在Java中的这个Serializable接口其实是给jvm看的,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。如果我们没有自己声明一个serialVersionUID变量,接口会默认生成一个serialVersionUID,默认的serialVersinUID对于class的细节非常敏感,反序列化时可能会导致InvalidClassException这个异常(每次序列化都会重新计算该值) 
AbstractList 继承了AbstractList ,说明它是一个列表,拥有相应的增,删,查,改等功能。 
List 为什么继承了 AbstractList 还需要 实现List 接口?
1、在StackOverFlow 中:传送门 得票最高的答案的回答者说他问了当初写这段代码的 Josh Bloch,得知这就是一个写法错误。  I’ve asked Josh Bloch, and he informs me that it was a mistake.He used to think, long ago, that there was some value in it,  but he since “saw the light”.Clearly JDK maintainers haven’t considered this to be worth backing out later. 
基本属性   private  static  final  long  serialVersionUID = 8683452581122892189L ;private  static  final  int  DEFAULT_CAPACITY = 10 ;private  static  final  Object[] EMPTY_ELEMENTDATA = {};private  static  final  Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};transient  Object[] elementData;private  int  size;
 
构造器   public  ArrayList ()   {    this .elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }      public  ArrayList (int  initialCapacity)   {    if  (initialCapacity > 0 ) {         this .elementData = new  Object[initialCapacity];     } else  if  (initialCapacity == 0 ) {         this .elementData = EMPTY_ELEMENTDATA;     } else  {         throw  new  IllegalArgumentException("Illegal Capacity: " + initialCapacity);     } }      public  ArrayList (Collection<? extends E> c)   {    Object[] a = c.toArray();     if  ((size = a.length) != 0 ) {         if  (c.getClass() == ArrayList.class )  {             elementData = a;         } else  {             elementData = Arrays.copyOf(a, size, Object[].class ) ;         }     } else  {                  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); } 
 
插入性能与linkedList对比 
package  jdk8.list;import  java.util.ArrayList;import  java.util.LinkedList;import  java.util.List;public  class  EffectTest   {    public  static  void  main (String[] args)   {                  int  length = 10000000 ;                  List arrayList = new  ArrayList(length);         List linkedList = new  LinkedList();         long  start5 = System.currentTimeMillis();         for (int  i=0 ;i <length;i++){             arrayList.add(i);         }         long  end5 = System.currentTimeMillis();         System.out.println("arrayList:" +(end5-start5));         long  start6 = System.currentTimeMillis();         for (int  i=0 ;i <length;i++){             linkedList.add(i);         }         long  end6 = System.currentTimeMillis();         System.out.println("linkedList:" +(end6-start6));     }                } 
 
arrayList涉及扩容,会消耗性能但是如果提前指定容量,会提升性能,可以达到与linkedList相当,甚至超越 
 
指定下标插入 public  void  add (int  index, E element)   {         rangeCheckForAdd(index);          ensureCapacityInternal(size + 1 );          System.arraycopy(elementData, index, elementData, index + 1 ,             size - index);          elementData[index] = element;     size++; } 
 
时间复杂度为O(n),与移动的元素个数正相关 
扩容 private  void  grow (int  minCapacity)   {                         int  oldCapacity = elementData.length;                          int  newCapacity = oldCapacity + (oldCapacity >> 1 );                          if  (newCapacity - minCapacity < 0 )                 newCapacity = minCapacity;                          if  (newCapacity - MAX_ARRAY_SIZE > 0 )                 newCapacity = hugeCapacity(minCapacity);                          elementData = Arrays.copyOf(elementData, newCapacity);         }                  private  static  int  hugeCapacity (int  minCapacity)   {             if  (minCapacity < 0 )                  throw  new  OutOfMemoryError();             return  (minCapacity > MAX_ARRAY_SIZE) ?                     Integer.MAX_VALUE :                     MAX_ARRAY_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 ;         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 ;     }          private  void  fastRemove (int  index)   {         modCount++;         int  numMoved = size - index - 1 ;         if  (numMoved > 0 )             System.arraycopy(elementData, index+1 , elementData, index,numMoved);         elementData[--size] = null ;     } 
 
迭代器 iterator public  Iterator<E> iterator ()   {     return  new  Itr(); }      private  class  Itr  implements  Iterator <E >  {         int  cursor;          int  lastRet = -1 ;          int  expectedModCount = modCount;               public  boolean  hasNext ()   {         return  cursor != size;     }     @SuppressWarnings ("unchecked" )     public  E next ()   {                           checkForComodification();         int  i = cursor;                  if  (i >= size)             throw  new  NoSuchElementException();         Object[] elementData = ArrayList.this .elementData;         if  (i >= elementData.length)             throw  new  ConcurrentModificationException();                  cursor = i + 1 ;                  return  (E) elementData[lastRet = i];     }     public  void  remove ()   {                  if  (lastRet < 0 )             throw  new  IllegalStateException();                  checkForComodification();         try  {                          ArrayList.this .remove(lastRet);                          cursor = lastRet;                          lastRet = -1 ;             expectedModCount = modCount;         } catch  (IndexOutOfBoundsException ex) {             throw  new  ConcurrentModificationException();         }     }     final  void  checkForComodification ()   {         if  (modCount != expectedModCount)             throw  new  ConcurrentModificationException();     } } 
 
remove 方法的弊端。  1、只能进行remove操作,add、clear 等 Itr 中没有。  2、调用 remove 之前必须先调用 next。因为 remove 开始就对 lastRet 做了校验。而 lastRet 初始化时为 -1。  3、next 之后只可以调用一次 remove。因为 remove 会将 lastRet 重新初始化为 -1 
fail-fast fail-fast机制是java集合中的一种错误机制。当使用迭代器迭代时,如果发现集合有修改,则快速失败做出响应,抛出ConcurrentModificationException异常。这种修改有可能是其它线程的修改,也有可能是当前线程自己的修改导致的,比如迭代的过程中直接调用remove()删除元素等。另外,并不是java中所有的集合都有fail-fast的机制。比如,像最终一致性的ConcurrentHashMap、CopyOnWriterArrayList等都是没有fast-fail的。  fail-fast是怎么实现的:  ArrayList、HashMap中都有一个属性叫modCount,每次对集合的修改这个值都会加1,在遍历前记录这个值到expectedModCount中,遍历中检查两者是否一致,如果出现不一致就说明有修改,则抛出ConcurrentModificationException异常。  底层数组存/取元素效率非常的高(get/set),时间复杂度是O(1),而查找(比如:indexOf,contain),插入和删除元素效率不太高,时间复杂度为O(n)。  插入/删除元素会触发底层数组频繁拷贝,效率不高,还会造成内存空间的浪费,解决方案:linkedList  查找元素效率不高,解决方案:HashMap(红黑树) 
注意事项 1.创建时指定最好初始长度,减少扩容次数提升效率 2.arrayList.subList(beginIndex,endIndex) 返回其内部类 通过指定偏移量操作原对象。(源对象不可变此处有fast-fail检查) 3.属性 modCount 每次添加删除元素 +1 fast-fail 检查 4.List unmodifiableList = Collections.unmodifiableList(list); 不可变list 原对象可变   
UnmodifiableList(List<? extends E> list) {     super (list);     this .list = list; } public  E get (int  index)   {return  list.get(index);}public  E set (int  index, E element)   {    throw  new  UnsupportedOperationException(); } public  void  add (int  index, E element)   {    throw  new  UnsupportedOperationException(); } public  E remove (int  index)   {    throw  new  UnsupportedOperationException(); } 
 
5.Arrays.asList(T..) 返回的是Arrays内部类。若传入的数组为基本类型,返回的list长度一直为1。 
Integer[] array = {1 ,2 ,3 }; List list = Arrays.asList(array); int [] array1 = {1 ,2 ,3 };List list1 = Arrays.asList(array1); 
 
6.List的最大长度为什么为 Integer.max-8