zoukankan      html  css  js  c++  java
  • JDK源码-ArrayList源码

    1,继承结构图:
         -1,ArrayList继承AbstractList抽象类,实现List、RandomAccess、Cloneable、Serializable接口。
         -2,查看List接口的继承关系,我们看到List接口实现了Collection接口。Collection接口是基本集合类接口。查看Collection接口的说明:
    /**
    * The root interface in the <i>collection hierarchy</i>. A collection
    * represents a group of objects, known as its <i>elements</i>. Some
    * collections allow duplicate elements and others do not. Some are ordered
    * and others unordered.
         -3,查看AbstractList分支继承关系,AbstractList继承AbstractCollection,实现List接口。
         -4,查看AbstractCollection,可以看到该类实现Collection接口。
         -5,Collection接口最终实现迭代器接口:Iterable。
    2,从用自上而下的方式来一步一步查看源码。
    3,Iterable接口:
    package java.lang;
     
    import java.util.Iterator;
     
    /** Implementing this interface allows an object to be the target of
    * the "foreach" statement.
    * @since 1.5
    */
    public interface Iterable<T> {
     
    /**
    * Returns an iterator over a set of elements of type T.
    *
    * @return an Iterator.
    */
    Iterator<T> iterator();
    }
    Iterable接口类源码很简单,我们知道该接口属于迭代器模式,用来实现迭代遍历集合类。所以Collection接口实现了该接口,标识Collecttion的所有子类都可以使用迭代器方式遍历。
    Iterable接口比较重要的子类我们可以看Iterator接口,如下,我摘录出了该接口的方法。
    public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
    }
    4,Collection接口,我们通过JavaDoc文档可以查看对应的子类
    * <p>This interface is a member of the
    * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    * Java Collections Framework</a>.
    *
    * @author Josh Bloch
    * @author Neal Gafter
    * @version 1.55, 04/21/06
    * @see Set
    * @see List
    * @see Map
    * @see SortedSet
    * @see SortedMap
    * @see HashSet
    * @see TreeSet
    * @see ArrayList
    * @see LinkedList
    * @see Vector
    * @see Collections
    * @see Arrays
    * @see AbstractCollection
    * @since 1.2
    */
    可以看到对应的都实现此接口,接口中定义了集合类常用到的方法。
    5,AbstractCollection
    public abstract class AbstractCollection<E> implements Collection<E>
    该类主要实现了部分共用的方法,比如:
    /**
    * {@inheritDoc}
    *
    * <p>This implementation returns <tt>size() == 0</tt>.
    */
    public boolean isEmpty() {
    return size() == 0;
    }
    public boolean contains(Object o) {
    Iterator<E> e = iterator();
    if (o==null) {
    while (e.hasNext())
    if (e.next()==null)
    return true;
    } else {
    while (e.hasNext())
    if (o.equals(e.next()))
    return true;
    }
    return false;
    }
    public boolean remove(Object o) {
    Iterator<E> e = iterator();
    if (o==null) {
    while (e.hasNext()) {
    if (e.next()==null) {
    e.remove();
    return true;
    }
    }
    } else {
    while (e.hasNext()) {
    if (o.equals(e.next())) {
    e.remove();
    return true;
    }
    }
    }
    return false;
    }
    public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    Iterator<? extends E> e = c.iterator();
    while (e.hasNext()) {
    if (add(e.next()))
    modified = true;
    }
    return modified;
    }
    主要实现了以上的方法,我们发现以上方法有个共同特点,就是具体操作是通过其他方法来实现的,比如addAll方法,主要是通过add方法来实现的。
    6,List接口,List接口继承了Collection接口,对Collection接口进行了一些扩展。
        -1,因为List存储的是顺序集合类。
    An ordered collection (also known as a <i>sequence</i>).
        -2,允许重复元素。
    Unlike sets, lists typically allow duplicate elements.
        -3,提供ListIterator来实现元素迭代。ListIterator继承自Iterator接口,并提供一些扩展方法。
    The <tt>List</tt> interface provides a special iterator, called a
    * <tt>ListIterator</tt>, that allows element insertion and replacement, and
    * bidirectional access in addition to the normal operations that the
    * <tt>Iterator</tt> interface provides.
        -4,提供一些其他扩展操作方法。
    7,ArrayList源码。
        -1,ArrayList是List的可变数组实现方式。实现了所有List接口的方法,大致同Vector类,只不过此类是不同步的。
               size  isEmpty  get  set  iterator  listIterator操作都以固定时间运行。即,添加n个元素需要O(n)事件运行,其他的操作也以线性时间运行。
                每个ArrayList都存在一个capacity的实例,该实例用来存储List对应数组的长度。
                在添加大数据操作时候,可以使用ensureCapacity操作来提前扩展大小。此操作是非线程安全的,如果多个线程同时访问一个ArrayList实例,而至少有一个线程从结构上(增加或者删除元素,或修改底层数组大小,不包含元素值的修改)修改了列表,那么它必须保持外部同步。一般通过封装该列表的对象进行同步操作来完成,如果不存该对象,可以使用Collections.synchronizedList方法包装列表实现。
    List list = Collections.synchronizedList(new ArrayList(...));
                使用迭代器遍历元素的时候,在创建迭代器之后,除非通过迭代器自身的remove或add方法从结构上对列表进行修改,否则在任何时间以任何方式修改都会抛出异常。
        以上均为API对ArrayList的描述。我们可以使用代码对以上内容进行测试:
        a. 测试  size  isEmpty  get  set  iterator  listIterator  add方法时间。
        
    public class TestAdd {
     
    public static void main(String[] args) {
    long startTime = System.currentTimeMillis();
    List<Integer> lists = new ArrayList<Integer>();
    //测试add方法
    for(int i = 0 ; i < 1000000; i++){
    lists.add(1);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("add添加1000000元素,用时: " + (endTime - startTime));//输出32
    //add 一个元素的时间
    startTime = System.currentTimeMillis();
    lists.add(2);
    endTime = System.currentTimeMillis();
    System.out.println("add添加1元素,用时: " + (endTime - startTime));//输出0
    //get 一个元素
    startTime = System.currentTimeMillis();
    lists.get(2);
    endTime = System.currentTimeMillis();
    System.out.println("get元素,用时: " + (endTime - startTime));//输出0
    }
    }
       b.  使用capacity元素完成初始化操作:
    long startTime = System.currentTimeMillis();
    List<Integer> lists = new ArrayList<Integer>(1000000);
    //测试add方法
    for(int i = 0 ; i < 1000000; i++){
    lists.add(1);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("add添加1000000元素,用时: " + (endTime - startTime));//输出12
       c.使用迭代器遍历ArrayList
        
    startTime = System.currentTimeMillis();
    Iterator<Integer> iter = lists.iterator();
    int a ;
    while(iter.hasNext()){
    a = iter.next();
    }
    endTime = System.currentTimeMillis();
    System.out.println("迭代器元素,用时: " + (endTime - startTime));//输出33
    -2,成员变量:
        elementData: 数组,用来存储ArrayList对应的元素列表。使用capacity来存储数组长度。
    private transient Object[] elementData;
        size:ArrayList存储元素的长度。
        modCount:此变量属于父类AbstractList。该元素记录了从结构上修改次列表的次数。此字段由iterator和listIterator方法返回的迭代器和列表迭代器实现。
        -3,构造函数:
        public ArrayList(int initCapacity):如果初始化参数小于0则抛出异常,否则初始化列表中的数组。
    public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
    throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
    this.elementData = new Object[initialCapacity];
    }
        public  ArrayList():初始化一个长度为10的数组。
    public ArrayList() {
    this(10);
    }
        public ArrayList(Collection<? extends e> c):构建一个包含c中所有元素的列表,元素顺序按照Iterator返回的顺序排列。
    public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();//转为数组
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)//如注释c.toArray可能返回非数组对象,所以此处需要判断,确保返回的为数组对象
    elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    使用到了Arrays.copyOf方法,我们可以进一步查看该方法:
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    T[] copy = ((Object)newType == (Object)Object[].class)
    ? (T[]) new Object[newLength]
    : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
    Math.min(original.length, newLength));
    return copy;
    }
    查看System.arraycopy源码:
    public static native void arraycopy(Object src, int srcPos,
    Object dest, int destPos,
    int length);
        -4,方法:
        add(E e):添加对应元素到数组中。add方法记调用了ensureCapacity方法,保证数组元素不越界,然后对数组元素的末尾增加了当前元素。
    public boolean add(E e) {
    ensureCapacity(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
    }
        ensureCapacity(int minCapacity):该方法判断数组元素是否已经超过了当前ArrayList中的数组长度,如果超过则增加长度。
    public void ensureCapacity(int minCapacity) {
    modCount++;
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
    Object oldData[] = elementData;
    int newCapacity = (oldCapacity * 3)/2 + 1;
    if (newCapacity < minCapacity)
    newCapacity = minCapacity;
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    }
        add(int index, E element):在数组固定位置添加元素。
         remove(int index):移除制定索引的元素。
    public E remove(int index) {
    RangeCheck(index);//确保索引位置未超出最大size,超出则抛出异常。
     
    modCount++;//记录表结构修改计数器
    E oldValue = (E) elementData[index];
     
    int numMoved = size - index - 1;
    if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
    numMoved);//将后续元素均向前移动一位
    elementData[--size] = null; // Let gc do its work
     
    return oldValue;
    }
        get(int index):获取制定索引元素
    public E get(int index) {
    RangeCheck(index);
     
    return (E) elementData[index];
    }
        set(int index, E e):更换制定索引元素值,使用e替换,并返回原有值。

    ArrayList的操作基本都很简单,包括源代码,相对来说还是比较简单。看此处的代码的时候,建议先学习数据结构的线性表后,再来看次部分的代码。
    欢迎转载,但转载请注明原文链接[博客园: http://www.cnblogs.com/jingLongJun/]
    [CSDN博客:http://blog.csdn.net/mergades]。
    如相关博文涉及到版权问题,请联系本人。
  • 相关阅读:
    secureCRT 实现windows和linux文件互传
    Mybatis Generator最完整配置详解
    部署Maven项目到tomcat报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    阿里云服务器实战: Linux MySql5.6数据库乱码问题
    如何将 Java 项目转换成 Maven 项目
    Windows7下Maven环境搭建及其使用
    Java HashMap工作原理及实现
    关于tomcat部署应用的三种方式
    关于浏览器缓存
    MySql使用存储过程实现事务的提交或者回滚
  • 原文地址:https://www.cnblogs.com/jingLongJun/p/4491055.html
Copyright © 2011-2022 走看看