关闭

Java Collection ArrayList

标签: javacollectionArrayList
369人阅读 评论(0) 收藏 举报
分类:

ArrayList是实现List接口的动态数组.实现了所有的list的操作,可以操作所有的元素,包括null值。除了实现List这个接口,ArrayList还提供方法去操作array的长度.这个特性被用来储存这个list.ArrayList和Vector差不多,除了它不是同步的.

在ArrayList中size, isEmpty, get, set, iterator, 和 listIterator这些操作是常数时间复杂度.add操作运行在常数的时间复杂度就是添加n个元素需要O(n)次数。所有的其它操作也是线性的时间复杂度.这个常量与LinkedList相比是低的。

每一个ArrayList实例都有一个capacity。这个capacity是这个array的长度用来储存这个list当中的元素。当ArrayList中被添加一个元素的时候,如果超过了限制capacity会自动增长的.

注意:这种List的实现不是synchronized的。如果多个线程访问一个ArrayList实现,并且至少其中一个线程改变这个线程的结构.它必须synchronized.(结构修改包含很多操作,比如说:添加或者删除一个或者多个元素,或者resize这个ArrayList中数组的大小.只是set其它一个元素的值不是改变它的结构)。一种典型的方法就是把这个ArrayList包装一下,可以使用Collections.synchronizedList方法来包装ArrayList。这是最好的方法在创建这个对象的时候,这样可以防止操作这个list会出现不同步的情况.

List list = Collections.synchronizedList(new ArrayList(...));

下面我们来分析一下ArrayList中的继承关系与源码:

1、类结构

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

由上面我们可以看到:
1. ArrayList可以看出它是支持泛型的,它继承自AbstractList,实现了List、RandomAccess、Cloneable、Java.io.Serializable接口.
2. AbstractList提供了List接口的默认实现(个别方法为抽象方法)。
3. List接口定义了列表必须实现的方法。
4. RandomAccess是一个标记接口,接口内没有定义任何内容。
5. 实现了Cloneable接口的类,可以调用Object.clone方法返回该对象的浅拷贝。
6. 通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。序列化接口没有方法或字段,仅用于标识可序列化的语义。

2、类属性

    /**
     * 默认的初始化capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 共享的array的空实例用于ArrayList的空实例
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 这个array用来存储ArrayList的元素.
     * ArrayList的capacity是这个array的长度.
     * elementData == EMPTY_ELEMENTDATA将会暴露给当使用DEFAULT_CAPACITY且第一次添加元素的时候
     */
    private transient Object[] elementData;

    /**
     * 这个ArrayList的长度(包含的元素个数).
     *
     * @serial
     */
    private int size;

    /** ArrayList实例被修改的次数 */
    protected transient int modCount = 0;

3、add – 添加元素

上面我们只是粗浅的认识了一下ArrayList的类继承关系与内部属性,下面我们来看看其中的方法.其中最重要的就是add方法.这个方法是把添加的元素追加到list实例的end.下面是内部方法的调用图.先有一个大体的印象.
这里写图片描述

1) add

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

add,先确认这个方法这个list的capacity,然后再添加这个元素。
2) ensureCapacityInternal

    private void ensureCapacityInternal(int minCapacity) {
        // 如果这个数据是空数组就设置list最小的capactity
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        // 确定明显的capacity
        ensureExplicitCapacity(minCapacity);
    }

3) ensureExplicitCapacity

    private void ensureExplicitCapacity(int minCapacity) {
        // 修改次数加1
        modCount++;

        // 如果最小的capacity比这个list最大储存长度还大扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

4) grow

    private void grow(int minCapacity) {
        // 数组之前的长度
        int oldCapacity = elementData.length;
        // 新长度为之前长度的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 数组copy
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

由上面我们可以看出ArrayList可以帮我们动态的扩容数组.但是如果我们知道我们需要添加数据的个数我们可以通过调用ArrayList的下面构造方法来指定list的储存能力.

    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

4、remove(int index) – 以下标删除元素(有返回值)

下面我们再来看一看remove方法.

    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; // clear to let GC do its work

        return oldValue;
    }

这里还是用到了System.arraycopy()来进行元素删除.并且返回这个元素。

5、fastRemove – 以下标删除元素(无返回值)

我们可以看到这个方法是私有的.看这个方法,主要是为ArrayList的删除元素做准备.

    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            // 把数组index + 1的元素全部copy到index的位置(相当于删除index位置的元素)
            System.arraycopy(elementData, index+1, elementData, index, numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

fastRemove方法和remove方法差不多,只是fastRemove方法没有返回值.而remove(int index)方法返回被删除的对象。

6、remove(Object o) – 删除list中的对象

    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;
    }

这里删除ArrayList中的元素,是遍历删除(list允许对象重复).然后调用上面分析的fastRemove方法进行元素删除。

7、indexOf(Object) – 查看对象在list第一次出现的位置

    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;
    }

这个方法是遍历ArrayList,返回找到的第一个与这个对象equals的index.如果没有就返回-1.

当然这里并没有分析ArrayList的全部方法。只分析了其中几个比较关键的方法。抛专引玉,大家可以自行去看ArrayList的源码。

0
0
查看评论

Java Collection笔记之ArrayList

1、前言ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。 ArrayList 继承了Abstrac...
  • p_3er
  • p_3er
  • 2016-03-15 16:34
  • 1466

Simple-Java—Collections(二)Java中如何把数组转换为ArrayList

Java中如何把数组转换为ArrayList
  • z55887
  • z55887
  • 2016-02-18 22:24
  • 1429

java集合Collection的List ArrayList LinkedList 区别

先说结论: 1、List的特点:线性顺序存储元素、元素可重复、可以存放null、可查找。 2、ArrayList(数组,中间插入删除慢、按位置查找快)、LinkedList(链表,中间插入删除快、按位置查找慢)   ==============正文============ 一、List特点...
  • escore
  • escore
  • 2017-06-23 08:49
  • 267

使用集合arrayList的时候为什么用它的父类Collection

Collection arrayList = new ArrayList List list = new ArrayList 我们有时候会遇到上面的代码,不理解为什么这么写,下面我来分享一下自己的想法: 首先,当我们在写程序的时候不知道应该用哪一个集合更好的时候就可以这么写,直接使用父类,...
  • wybchy
  • wybchy
  • 2017-08-12 13:08
  • 197

public ArrayList(Collection<? extends E> c)中的 ? 和 E 是什么意思

上面那句话是ArrayList ?是“任意类”的意思,extends继承不多说,E是指定类型。 首先,楼上说的不错,是泛型。这是java 1.5以后引入的。 从此以后,定义一个空的ArrayList需要这样,比如我需要一个MyClass的顺序表,则: ArrayList myList = new...
  • wuxinliulei
  • wuxinliulei
  • 2014-08-10 21:40
  • 4622

java之14天 Collection,Vectory,ArrayList集合 (一)

Collection集合框架 import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /*** *Cellecti...
  • luobing_csdn
  • luobing_csdn
  • 2017-03-27 11:19
  • 208

Collection<String>n=new ArrayList<String>()与List<String>n=new ArrayList()的区别

JAVA这样的定义:Collectionn=new ArrayList()与Listn=new ArrayList()的区别 Collection 和 List都是抽象类。提供了通用的方法。 List是Collection的子类,增加了一些方法,ArrayList是List的子类,又增加...
  • u010655348
  • u010655348
  • 2016-10-14 22:54
  • 2690

Java - Collection

collection层次结构 理论 集合中存放的依然是对象的引用而不是对象 集合中只能放置对象的引用,不能放置原生数据类型, 我们需要使用原生数据类型的封装类才能加入到集合中 集合中放置的都是Object类型,因此取出来的只能是Object类型 List称为序列 List接口用户可以对列表...
  • itlwc
  • itlwc
  • 2013-08-21 15:13
  • 37243

【Java】为ArrayList去重

ArrayList没有封装好的去重方法,比如对于一个[2, 5, 2, 3, 2, 4]的ArrayList,我要去除其中的重复的元素, 我也不想把语句也这么长,也不想用for循环的方法去重,那么可以先考虑把ArrayList转化为一个临时的HashSet,再把这个临时的HashSet转化回Arr...
  • yongh701
  • yongh701
  • 2015-01-29 09:46
  • 5192

浅谈Java中Collection、Iterable、List、ArrayList间的关系

Java是一个高级语言,它提供了很多现成的数据结构,给我们的编程带来了极大的遍历。这都是由Java编程的高手给出的,学习这里面的实现方式无论是对于我们使用这些工具还是对于掌握Java的编程之道都是很有帮助的。本文主要讲述Java中的表的实现方式。        ...
  • Judy_c
  • Judy_c
  • 2017-10-13 20:42
  • 249
    个人资料
    • 访问:230699次
    • 积分:3849
    • 等级:
    • 排名:第9862名
    • 原创:134篇
    • 转载:45篇
    • 译文:28篇
    • 评论:105条
    个人简介
    请作者喝杯咖啡吧。
    博客专栏
    最新评论