JAVA笔记:集合系列02—ArrayList

来源:互联网 发布:阿里云华北2速度 编辑:程序博客网 时间:2024/05/22 10:19

ArrayList的继承关系

         java.lang.Object
           ↳     java.util.AbstractCollection<E>
                ↳     java.util.AbstractList<E>
                      ↳     java.util.ArrayList<E>

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


第1部分 ArrayList介绍

     a. ArrayList继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
     b. ArrayList实现了RandomAccess接口,即提供了随机访问功能。

         RandomAccess是java中用来被List实现,为List提供快速访问功能的。

         在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
     c. ArrayList实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
     d. ArrayList实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。


     ArrayList中的操作不是线程安全的。所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

     ArrayList是一个数组队列(采用数组来存放集合元素),如果容量不够时,通过重新创建数组拷贝旧集合的方式来实现动态数组,所以尽量在使用之前分配足够内存并且尽量小的内存来存放集合,否则资源极大浪费降低性能。

     ArrayList每次扩容增加原来一半的容量,但不能够超过INTEGER最大值的容量。


第2部分 ArrayList详细介绍

    a.AbstractList详细介绍

             // 将元素插入到List集合的location处

             void add(int location, E object);

             // 将集合插入到List集合的location处

             boolean addAll(int location, Collection<? extends E> collection);

             // 删除并返回location索引处的旧元素

             E remove(int location);

             // 移除fromIndex(包含)~toIndex(不包含)的元素

             protected void removeRange(int fromIndex, int toIndex);

             // 返回集合location索引处的元素

             E get(int location);

             // 将location索引处的元素替换为object,并返回旧的元素

             E set(int location, E object);

             // 返回object在集合中第一个出现的位置索引,没有找到返回-1

             int indexOf(Object object);

             // 返回object在集合中最后一次出现的位置索引,没有找到返回-1

             int lastIndexOf(Object object);

             // 返回location索引开始的List迭代

             ListIterator<E> listIterator(int location);

             // 返回List迭代器

             ListIterator<E> listIterator();

             // 返回start(包含)~end(不包含)的子集合

             List<E> subList(int start, int end);

     b.ArrayList详细介绍

            // 克隆

            Object clone();

            // 扩容数组,最小容量为minimumCapacity

            void ensureCapacity(int minimumCapacity);

           // 收缩数组,数组的长度=元素的个数

            void trimToSize();

 

第3部分 ArrayList源码解析

a.容量操作源码

       // 定义最大数组容量

       private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

       // 获取巨大数组容量,不能够超过integer的最大值

       private static int hugeCapacity(int minCapacity) {
           if (minCapacity < 0) // overflow
               throw new OutOfMemoryError();
           return (minCapacity > MAX_ARRAY_SIZE) ?
               Integer.MAX_VALUE :
               MAX_ARRAY_SIZE;
         }

        // 扩容数组,每次扩容增加一半容量

        private void grow(int minCapacity) {
           // overflow-conscious code
           int oldCapacity = elementData.length;
           int newCapacity = oldCapacity + (oldCapacity >> 1);
           if (newCapacity - minCapacity < 0)
               newCapacity = minCapacity;
           if (newCapacity - MAX_ARRAY_SIZE > 0)
               newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
           elementData = Arrays.copyOf(elementData, newCapacity);
       }

     // 每次调用保证容量,不管有没有扩容,修改计数器都会增1,这个是fail-fast抛出异常的关键所在

      // 增加、删除、清空等操作都会调用保证容量方法,也就会修改计数器,从而保证fail-fast机制

      // 注意:集合的交集、差集操作不会影响修改计数器,也就不会导致fail-fast机制

      private void ensureCapacityInternal(int minCapacity) {
           modCount++;
           // overflow-conscious code
           if (minCapacity - elementData.length > 0)
               grow(minCapacity);
       }

      public void ensureCapacity(int minCapacity) {
           if (minCapacity > 0)
               ensureCapacityInternal(minCapacity);
       }

       // 每次调用收缩容量,修改计数器都会增1,这个是fail-fast抛出异常的关键所在

       public void trimToSize() {
           modCount++;
           int oldCapacity = elementData.length;
           if (size < oldCapacity) {
               elementData = Arrays.copyOf(elementData, size);
           }
       }

b.查找元素源码

    // 通过传入对象的equals来判断是否相等,如果重写equals,直接返回true,则返回索引肯定是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;
    }

c.Iterator迭代器遍历,通过内部类的方式实现

     // 如果被迭代的集合元素还没有被遍历,则返回true

     boolean hasNext();

    // 返回集合里的下一个元素

     Object next();

     // 删除集合里上一次next方法返回的元素

     void remove(); 

d.listIterator迭代器遍历,通过内部类的方式实现,并且继承Iterator

     // 返回该迭代器关联的集合是否还有上一个元素

     boolean hasPrevious();

    // 返回集合里的上一个元素

     Object previous();

     // 在指定位置插入一个元素

     void add(E e);      

     // 在指定位置设置元素

     void set(E e);   

第4部分 ArrayList遍历方式

ArrayList支持3种遍历方式

a.通过迭代器遍历(效率最慢,要创建对象等开销)

Integer value = null;

Iterator iter = list.iterator();

while(iter.hasNext())

{

  value = (Integer)iter.next();

}

b.随机访问,通过索引值去遍历(效率最快)

Integer value = null;

int size = list.size();

for(int i=0; i<size;i++)

{

   value = (Integer)list.get(i);

}

c.for循环遍历

Integer value = null;

for (Integer integ: list)

{

  value = integ;

}

原创粉丝点击