zoukankan      html  css  js  c++  java
  • ArrayList、LinkedList、Vector、CopyOnWriteArrayList的区别和源码分析

    1. ArrayList

    ArrayList 是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。默认容量是10(从源码中可以看出每次容量扩大为原来的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);)。ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
        ......
        
        /**
         * Default initial capacity.
         */
        private static final int DEFAULT_CAPACITY = 10;
    
        public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            }
        }    
        
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
        
        public ArrayList(Collection<? extends E> c) {
            ......
        }
    
        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);
            }
    
        public int size() {
            return size;
        }
    
           ......
    }

    1.1 ArrayList的扩容

    ArrayList的默认容量为10,当插入第11个元素的时候就会扩容,每次扩容增大为原来的1.5倍,可从代码int newCapacity = oldCapacity + (oldCapacity >> 1);看出。

    2. LinkedList

    LinkedList和ArrayList一样实现了List接口,但是LinkedList是用双向链表实现的。

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
           transient int size = 0;
    
        transient Node<E> first;
    
        transient Node<E> last;
    
        public LinkedList() {
            }
    
        private static class Node<E> {
                E item;
                Node<E> next;
                Node<E> prev;
    
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                        this.next = next;
                        this.prev = prev;
                    }
            }
    
        ......
    }

    2.1 ArrayList和LinkedList的区别

    • 遍历都可以使用普通for循环、foreach循环、Iterator接口实现
    • ArrayList基于数组实现,LinkedList基于双向链表实现
    • ArrayList随机访问和修改的效率比较高,LinkedList插入和删除的效率比较高

    3. Vector

    Vector是线程安全的,从源码中有很多的synchronized就可以看出。Vector是Java早期提供的线程安全的动态数组,synchronized关键字几乎修饰了所有对外暴露的方法,所以在读远大于写的操作场景中,Vector将会发生大量锁竞争,从而给系统带来性能开销。适用于写大于读的场景

    public class Vector<E>
        extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
        ......
        protected Object[] elementData;
        protected int elementCount;
        protected int capacityIncrement;
    
        public Vector(int initialCapacity) {
                this(initialCapacity, 0);
        }
    
        public Vector() {
                this(10);
            }
        
        public synchronized int capacity() {
                return elementData.length;
            }
    
        public synchronized int size() {
                return elementCount;
            }
        ......
    }

    ArrayList和Vector的区别

    • Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。所以在单线程中,ArrayList比Vector性能要高
    • ArrayList和Vector底层都采用数组进行连续存储,当存储空间不足需要扩容的时候,ArrayList默认增加为原来的1.5倍,Vector默认增加为原来的2倍
    • 查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用Vector和ArrayList都可以

    4. CopyOnWriteArrayList

    CopyOnWriteArrayList具有如下特性:

    • 实现了List接口;
    • 内部持有一个ReentrantLock lock = new ReentrantLock();
    • 增加时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
    • 增删改都需要获得锁,并且锁只有一把,而读操作不需要获得锁,支持并发。为什么增删改中都需要创建一个新的数组,操作完成之后再赋给原来的引用?这是为了保证get的时候都能获取到元素,如果在增删改过程直接修改原来的数组,可能会造成执行读操作获取不到数据;
    • 内部使用ReentrantLock保证线程安全;

    CopyOnWriteArrayList是java.util.concurrent包提供的方法,它实现了读操作无锁写操作则通过操作底层数组的新副本来实现,是一种读写分离的并发策略。 

    CopyOnWrite它的原理是,任何修改操作,如add、set、remove,都会拷贝原数组,修改后替换原来的数组,通过这种防御性的方式,实现另类的线程安全。

    所以这种数据结构,相对比较适合读多写少的操作,不然修改的开销还是非常明显的,适用于读远大于写的场景

    public class CopyOnWriteArrayList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
            private static final long serialVersionUID = 8673264195747942595L;
        
        /** The lock protecting all mutators */
        final transient ReentrantLock lock = new ReentrantLock();
        
        /** The array, accessed only via getArray/setArray. */
        private transient volatile Object[] array;
    
        public boolean add(E e) {
                final ReentrantLock lock = this.lock;
                lock.lock();
                try {
                    Object[] elements = getArray();
                    int len = elements.length;
                    Object[] newElements = Arrays.copyOf(elements, len + 1);
                    newElements[len] = e;
                    setArray(newElements);
                    return true;
                } finally {
                    lock.unlock();
                }
            }
        
        }
    
        ......
    }
  • 相关阅读:
    解决MySQL报错The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents .....
    不安装Oracle客户端,用plsql连接远程Oracle数据库(绝对解决你的问题)
    Java中的String,StringBuilder,StringBuffer三者的区别
    字符串截取的常用方法
    java 项目 导入成功后jsp页面报错处理方法
    PL/SQL Developer安装详解(32位客户端免安装版)
    oracle 11g如何完全卸载
    Struts2下载文件点取消出现的异常解决
    Web框架们
    Django【进阶篇 】
  • 原文地址:https://www.cnblogs.com/windpoplar/p/11886116.html
Copyright © 2011-2022 走看看