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)

	    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的操作基本都很简单,包括源代码,相对来说还是比较简单。看此处的代码的时候,建议先学习数据结构的线性表后,再来看次部分的代码。

时间: 2024-10-10 00:34:28

JDK源码-ArrayList源码的相关文章

jdk 1.7 ArrayList 源码分析

1.首先看看ArrayList 的基类有哪些 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 可以总结为: ArrayList 继承了AbstractList 实现了 List . RondomAcess . cloneable . serializable 对于一般的容器都会实现clon

给jdk写注释系列之jdk1.6容器(1):ArrayList源码解析

原文出自吞噬天地,链接整理自ImportNew 给jdk写注释系列之jdk1.6容器(2):LinkedList源码解析 给jdk写注释系列之jdk1.6容器(3):Iterator设计模式 给jdk写注释系列之jdk1.6容器(4)-HashMap源码解析 给jdk写注释系列之jdk1.6容器(5)-LinkedHashMap源码解析 给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器 给jdk写注释系列之jdk1.6容器(1):ArrayList源码解析 工作中

【Java集合源码剖析】ArrayList源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/35568011 ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的C

Java集合干货系列-(一)ArrayList源码解析

前言 今天来介绍下ArrayList,在集合框架整体框架一章中,我们介绍了List接口,ArrayList继承了AbstractList,实现了List.ArrayList在工作中经常用到,所以要弄懂这个类是极其重要的.构造图如下:蓝色线条:继承绿色线条:接口实现 正文 ArrayList简介 ArrayList定义 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomA

Java笔记---ArrayList源码分析

一.前言 一直就想看看java的源码,学习一下大牛的编程.这次下狠心花了几个晚上的时间,终于仔细分析了下 ArrayList 的源码(PS:谁说的一个晚上可以看完的?太瞎扯了).现在记录一下所得. 二.ArrayList 源码分析 2.1 如何分析? 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 Eclipse 找到所需要分析的类(此处就是 ArrayList) 新建类:新建一个类,命名为 ArrayList,将源码拷贝到该类.因为我

转:【Java集合源码剖析】ArrayList源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/35568011   本篇博文参加了CSDN博文大赛,如果您觉得这篇博文不错,希望您能帮我投一票,谢谢! 投票地址:http://vote.blog.csdn.net/Article/Details?articleid=35568011   ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayL

java8 ArrayList源码阅读

转载自 java8 ArrayList源码阅读 本文基于jdk1.8 JavaCollection库中有三类:List,Queue,Set 其中List,有三个子实现类:ArrayList,Vector,LinkedList http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java 实现原理 transient Object[] elementData; // 存放元素

ArrayList 源码解读

ArrayList 源码解读     基于JDk 1.7.0_80 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable ArrayList的底层是使用数组实现的,因为数组的容量是固定的,要实现可变容量List,所以一定存在着容量检测,数组复制等方法. 对象属性 /** * 默认大小 */ pr

集合类学习之Arraylist 源码分析

1.概述 ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小. 每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小.它总是至少等于列表的大小(如果不指定capacity,默认是10).    /**      * Constructs an empty list with an initial capacity of ten.