Collection集合-01.ArrayList

1.ArrayList

1.1 实现了Access接口

实现标记接口Access有以下特点

  • 目的是允许通用算法提供良好的性能
  • 当遍历方式不同,速度不同时,通常需要继承这个接口

1.2 ArrayList 的迭代器

1.2.1 Iterator

  • 继承Itrator接口
private class Itr implements Iterator<E> 
  • hasNext()方法通过游标和数组长度进行比较判断
public boolean hasNext() {
            return cursor != size;
        }
  • next()接口,获取游标所在位置的元素,游标向后移动一个位置;
 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];//设置lastRet为i,lastRet是锁定元素
        }
  • remove()方法,主要经过了以下几个步骤:
    • 删除当前位置lastRet锁定位置的值;(ArrayList的remove方法的删除,其实是将数组元素移动1个位置重新copy)
    • 删除后cursor = lastRet,也就意味着将游标指向 锁定元素的位置;
    • 将锁定元素设置为-1;
      从上面的步骤可以看出:
      1.当iterator没有移动使用next()方法,lastRet是-1,调用ArrayList的remove方法会报错;
      2.并且使用iterator逐个删除元素的时候,必须在remove之前用next()方法移动游标,将锁定元素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();
    }
}

======ArrayList 的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;
    }

1.2.1 ListIterator

  • 1.继承Iterator实现类,并实现了ListIterator接口
    就是对iterator接口方法的扩充
 private class ListItr extends Itr implements ListIterator<E>
  ListItr(int index) {
            super();
            cursor = index;
        }
  • 2.previous方法 ,将游标cursor移动到前一个位置,并设置lastRet为当前的元素i;
     public E previous() {
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }
  • 3.set方法,根据lastRet的位置设置,不能在cursor为0时设置;add方法,是将ArrayList的元素从index+1拷贝重生成;
public void set(E e) {
      if (lastRet < 0)
          throw new IllegalStateException();
      checkForComodification();

      try {
          ArrayList.this.set(lastRet, e);
      } catch (IndexOutOfBoundsException ex) {
          throw new ConcurrentModificationException();
      }
  }

  public void add(E e) {
      checkForComodification();

      try {
          int i = cursor;
          ArrayList.this.add(i, e);
          cursor = i + 1;
          lastRet = -1;
          expectedModCount = modCount;
      } catch (IndexOutOfBoundsException ex) {
          throw new ConcurrentModificationException();
      }
  }

1.3 SubList子列表

  • 获取ArrayList的区间进行操作,可以使用ArrayList的所有操作
SubList(AbstractList<E> parent,
             int offset, int fromIndex, int toIndex) {
      this.parent = parent;
      this.parentOffset = fromIndex;
      this.offset = offset + fromIndex;
      this.size = toIndex - fromIndex;
      this.modCount = ArrayList.this.modCount;
  }

1.4 ArrayListSpliterator

1.ArrayList集合中获取

初始的index 是0,fence是-1
   ======== ArrayList ==========
    @Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }
    ===== ArrayListSpliterator 构造函数 ====
     ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // OK if null unless traversed
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

2.进行分栏操作

  进行二分操作,返回的是以index为首,中间值mid为fence的新的ArrayListSpliterator
 //fence大小为 list的size
 public ArrayListSpliterator<E> trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
    return (lo >= mid) ? null : // divide range in half unless too small
        new ArrayListSpliterator<E>(list, lo, index = mid,
                                    expectedModCount);
}

3.forEachRemaining

就是将剩余的元素进行遍历

if ((i = index) >= 0 && (index = hi) <= a.length) {
    for (; i < hi; ++i) {
        @SuppressWarnings("unchecked") E e = (E) a[i];
        action.accept(e);
    }
    if (lst.modCount == mc)
        return;
}

4.主要的作用是当大数据list进行遍历处理时,可以进行切分

示例代码如下:
在实际使用中,可以用多线程处理

public class ArrayListTest {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("zhangsan");
        list.add("wangwu");
        list.add("zhaoliu");
        list.add("job");
        list.add("tom");
        Spliterator<String> spliterator = list.spliterator();
        Spliterator<String> s1 = spliterator.trySplit();
        spliterator.forEachRemaining(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        s1.forEachRemaining(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
    }

}
==========  输出的结果 =============
zhaoliu
job
tom
zhangsan
wangwu

1.5 基本属性

1.ArrayList元素存储及扩容

  • 默认为空数组,也可通过构造函数传参,确定初始容量大小
  • Object 数组存储元素
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
      this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  }

  • Object数组进行扩容,首次add数据初始化最小为10
    private void ensureCapacityInternal(int minCapacity) {//传入最小的容量
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    private static final int DEFAULT_CAPACITY = 10;  
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
     private void grow(int minCapacity) { //将object数组进行扩容
        // 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.ArrayList,底层是通过Object对象数组存储对象,并不是通过泛型数组存储;
2.默认初始化为空数组,首次初始化最小容量为10;
3.提供了iterator,和listIterator两个子类,用于遍历使用;
4.iterator遍历删除要先用next()移动游标,否则会报错;
5.ListIterator的set方法使用,必须要进行游标移动;
6.SubList是对ArrayList进行截取一部分进行操作;

posted @ 2020-05-25 11:21  PerfectLi  阅读(180)  评论(0编辑  收藏  举报