zoukankan      html  css  js  c++  java
  • ArrayList详解

                                           

                1.ArrayList继承AbstractList,该类的父类AbstractCollection实现了Collection接口。

                2.RandomAccess:是一个标识,其内部无任何定义,表名该类支持随机访问。

                3.Cloneable:能被克隆,实现了clone()方法,浅拷贝。

                4.Serializable:支持序列化,能通过序列化去传输。

    1.成员变量

    //默认初始容量大小
    private static final int DEFAULT_CAPACITY = 10;
    //共享空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //有初始容量的共享空数组
    private static final Object[] 
    DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //保存数据的数组
    transient Object[] elementData; 
    //元素个数
    private int size;

    2.构造器

    //参数为集合的长度
    public ArrayList(int initialCapacity) {
            //参数校验
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
                //长度为0,创建空数组
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            }
        }
    //无参构造器
    public ArrayList() {
            //创建有初始容量的空数组
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    //参数为Collection或其子类对象
    public ArrayList(Collection<? extends E> c) {
            //将集合转为数组
            elementData = c.toArray();
            if ((size = elementData.length) != 0) {
                //判断数组的类型是否为Object
                if (elementData.getClass() != Object[].class)
                    //若不是Object将其转为Object类型
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
            //若集合长度为0,创建空数组
            this.elementData = EMPTY_ELEMENTDATA;
            }
    }

    3.主要方法

    //该方法将数组长度改为集合中存在元素数量
    public void trimToSize() {
            modCount++;
            //若当前元素数量小于数组长度:为0则创建空数组,为其他值将数组长度压缩为当前集合中元素的数量。
            if (size < elementData.length) {
                elementData = (size == 0)
                  ? EMPTY_ELEMENTDATA
                  : Arrays.copyOf(elementData, size);
            }
    }

       扩容机制,以添加单个元素为例

    public boolean add(E e) {
            modCount++;
            //调用私有方法添加元素
            add(e, elementData, size);
            return true;
    }
    private void add(E e, Object[] elementData, int s) {
            //若当前元素数量已经与集合长度相同,就进行扩容,调用grow()
            if (s == elementData.length)
                elementData = grow();
            elementData[s] = e;
            size = s + 1;
    }
    private Object[] grow() {
            return grow(size + 1);
    }
    private Object[] grow(int minCapacity) {
            int oldCapacity = elementData.length;
            if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                //minCatacity为假若成功添加后元素数量,oldCapacity为当前集合长度,若minCapacity - oldCapacity < oldCapacity >> 1 ,newCapacity = oldCapacity >> 1  + oldCapacity,也就是1.5倍。否则newCapacity = minCapacity + oldCapacity 
                int newCapacity = ArraysSupport.newLength(oldCapacity,
                        minCapacity - oldCapacity, /* minimum growth */
                        oldCapacity >> 1           /* preferred growth */);
                return elementData = Arrays.copyOf(elementData, newCapacity);
            } else {
                //若数组为空,执行下述代码
                return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
            }
    }

    int size():返回集合中元素的数量

    boolean isEmpty():判断集合是否为空

    boolean contains(Object o):判断集合是否包含指定元素

    int indexOf(Object o):返回集合中首次出现元素o的索引

    int lastIndexOf(Object o):返回集合中最后一次出现元素o的索引

    Object[] toArray():将结合转为Object类型数组

    <T> T[] toArray(T[] a):将集合转为指定类型数组

    E get(int index):返回指定索引处元素

    E set(int index, E element):用指定元素替换指定索引处的元素

    boolean add(E e):在末尾添加元素

    void add(int index, E element):在指定位置处添加元素

    E remove(int index):移除指定索引处元素并返回该元素

    boolean remove(Object o):移除指定元素

    void removeRange(int fromIndexint toIndex):移除指定索引范围内元素,左闭右开

    void clear():清除集合中的所有元素

    boolean addAll(Collection<? extends E> c):将指定集合添加至该集合的尾部

    最后:向 ArrayList 添加大量元素之前最好先使用ensureCapacity 方法,以减少增量重新分配的次数。

    LinkedList:

                                              

                  1.AbstractSequentialList:定义了关于链表的一些操作

                  2.Deque:双端队列的缩写double ended queue

                  所以LinkedList既可作为链表使用,也可作为队列使用。(增删速度快,查询速度慢)

      作为队列:

        入队列:

    public boolean add(E e) {
            linkLast(e);
            return true;
    }
    void linkLast(E e) {
            //l为队列的最后一个节点
            final Node<E> l = last;
            //创建新节点newNode,其前一个节点是l,后一个节点为空
            final Node<E> newNode = new Node<>(l, e, null);
            //更新队列的最后一个节点
            last = newNode;
            //如果l为空,说明此时是一个空队列,更新first节点
            if (l == null)
                first = newNode;
            //LinkedList是双向链表,所以更新l的next的节点使其指向新节点
            else
                l.next = newNode;
            size++;
            modCount++;
    }

        出队列

    public E poll() {
            final Node<E> f = first;
            //判断队列的首节点是否为空:为空则没有节点可出队列,直接返回空。不为空则删除队列的第一个节点
            return (f == null) ? null : unlinkFirst(f);
    }
    private E unlinkFirst(Node<E> f) {
            // assert f == first && f != null;
            final E element = f.item;
            //保存首节点的下一节点
            final Node<E> next = f.next;
            f.item = null;
            //让首节点的next域为空
            f.next = null; // help GC
            //更新队列的首节点
            first = next;
            if (next == null)
                last = null;
            else
                next.prev = null;
            size--;
            modCount++;
            return element;
    }

      作为栈

        入栈

    //始终在头部插入,就能保证第一个节点为刚入栈
    public void push(E e) {
            addFirst(e);
    }
    public void addFirst(E e) {
            linkFirst(e);
    }
    private void linkFirst(E e) {
            final Node<E> f = first;
            final Node<E> newNode = new Node<>(null, e, f);
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
    }

        出栈

    //同样的道理:出栈时始终删除第一个元素,可保证先入后出
    public E pop() {
            return removeFirst();
    }
    public E removeFirst() {
            final Node<E> f = first;
            if (f == null)
                throw new NoSuchElementException();
            return unlinkFirst(f);
    }
    private E unlinkFirst(Node<E> f) {
            // assert f == first && f != null;
            final E element = f.item;
            final Node<E> next = f.next;
            f.item = null;
            f.next = null; // help GC
            first = next;
            if (next == null)
                last = null;
            else
                next.prev = null;
            size--;
            modCount++;
            return element;
    }
  • 相关阅读:
    在同步块中修改指向同步对象的引用
    算法学习记录3 插入排序
    算法学习记录2 归并排序
    算法学习记录1 快速排序
    CE学习记录1
    jenkins 学习记录2
    jenkins 学习记录1
    扩展 jquery miniui 组件实现自动查询数据
    java对象与XML相互转化
    分享公司缓存的用法
  • 原文地址:https://www.cnblogs.com/3w9898/p/14407880.html
Copyright © 2011-2022 走看看