• ArrayList 和 LinkList 的区别


    ArrayList 的相关知识

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

     由上面源码可知,Arraylist继承自AbstractList 实现了List ,Cloneable,Serializable,RandomAccess接口.其中Cloneable是克隆接口,Serializable是实现序列化操作的接口,便于对象的传输。而今天重点要描述一下这个RandomAccess。

     RandomAccess接口是一个标记接口,实现了它的list集合支持随机访问,目的是是算法在随机和随机访问时显得更灵活。在collections的 binarySearch源码如下

    public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
    return Collections.indexedBinarySearch(list, key);
    else
    return Collections.iteratorBinarySearch(list, key);
    }

    我们可以看到,他首先会判断这个list是否实现了RandomAccess接口,如果这个条件和list.size()<BINARYSEARCH_THRESHOLD(其中: BINARYSEARCH_THRESHOLD Collections的一个常量(5000),它是二分查找的阀值。)满足其中任何一个则使用Collections的indexedBinarySearch(list,key)方法。否则会调用Collections.iteratorBinarySearch(list,key)方法。

      这两者的代码实现分别如下:

    indexedBinarySearch 方法:

     

    1. private static <T>  
    2.     int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {  
    3.         int low = 0;  
    4.         int high = list.size()-1;  
    5.   
    6.         while (low <= high) {  
    7.             int mid = (low + high) >>> 1;  
    8.             Comparable<? super T> midVal = list.get(mid);  
    9.             int cmp = midVal.compareTo(key);  
    10.   
    11.             if (cmp < 0)  
    12.                 low = mid + 1;  
    13.             else if (cmp > 0)  
    14.                 high = mid - 1;  
    15.             else  
    16.                 return mid; // key found  
    17.         }  
    18.         return -(low + 1);  // key not found  
    19.     }  

    indexedBinarySearch 方法是直接通过get来访问元素

     

     

    iteratorBinarySearch方法

     
    1. private static <T>  
    2.     int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)  
    3.     {  
    4.         int low = 0;  
    5.         int high = list.size()-1;  
    6.         ListIterator<? extends Comparable<? super T>> i = list.listIterator();  
    7.   
    8.         while (low <= high) {  
    9.             int mid = (low + high) >>> 1;  
    10.             Comparable<? super T> midVal = get(i, mid);  
    11.             int cmp = midVal.compareTo(key);  
    12.   
    13.             if (cmp < 0)  
    14.                 low = mid + 1;  
    15.             else if (cmp > 0)  
    16.                 high = mid - 1;  
    17.             else  
    18.                 return mid; // key found  
    19.         }  
    20.         return -(low + 1);  // key not found  
    21.     }  

    iteratorBinarySearch中ListIterator来查找相应的元素

    在javadoc中指出人们认识到随机存取和顺序存取之间的区别通常是模糊的。例如,一些列表实现提供了渐进的线性访问时间,如果它们在实践中获得了巨大的、但持续的访问时间。这种接口通常应该实现这个接口。根据经验,列表实现应该实现这个接口,如果对于类的典型实例,这个循环:

    for (int i=0, n=list.size(); i < n; i++)
             list.get(i);
     

    runs faster than this loop:

         for (Iterator i=list.iterator(); i.hasNext(); )
             i.next();
    也就是说实现RandomAccess接口的的List可以通过简单的for循环来访问数据比使用iterator访问来的高效快速。
    回过头来,我们再说说ArrayList,

    {
    private static final long serialVersionUID = 8683452581122892189L;

    /**
    * The array buffer into which the elements of the ArrayList are stored.
    * The capacity of the ArrayList is the length of this array buffer.
    */
    private transient Object[] elementData;   //ArrayList的底层是一个基数组。

    /**
    * The size of the ArrayList (the number of elements it contains).
    *
    * @serial
    */
    private int size;

    /**
    * Constructs an empty list with the specified initial capacity.
    *
    * @param initialCapacity the initial capacity of the list
    * @exception IllegalArgumentException if the specified initial capacity
    * is negative
    */
    public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
    throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
    this.elementData = new Object[initialCapacity];
    }

    /**
    * Constructs an empty list with an initial capacity of ten.
    */
    public ArrayList() {
    this(10);    //默认的初始大小为10.

    }      

    public void ensureCapacity(int minCapacity) {  //给定所需的最小容量
    modCount++;
    int oldCapacity = elementData.length;    //原来数组中的元素大小
    if (minCapacity > oldCapacity) {//如果所需的最小容量大于 原数组中数据的个数时。
    Object oldData[] = elementData;
    int newCapacity = (oldCapacity * 3)/2 + 1;  //则要对旧的数组进行扩容,新数组的容量为原来的1.5倍+1
    if (newCapacity < minCapacity)//如果新的容量还是小于最小需求的容量,则将最小需求容量赋给新容量。
    newCapacity = minCapacity;
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);//在将就数组中的元素拷贝到新的容量数组中
    }
    }

    LinkedList 的相关知识

    public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable

    public LinkedList() {
    header.next = header.previous = header;
    }

    它的增添方法常用的是add(),删除常用的方法是remove(),它的底层是一个双向链表。

    对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 

    对于增添与删除add和remove,ArrayList需要挪动数据,除非是在数组末尾,需要消耗一定的时间,而LinkedList便可以很轻易地做到。

    总结ArrayList 和LinkedList的区别:

    1.两者继承的基类不一样。ArrayList 继承自AbstractList,而LinkedList继承自 AbstractSequentialList。

    2.底层结构不一样。ArrayList 采用的是动态数组,而LinkedList采用的是双向链表。

    3.ArrayList实现了RandomAccess接口,所以在随机访问时效率比较高。而LinkedList需要不停地移动指针。

    4.对于增添与删除add和remove,ArrayList需要挪动数据,除非是在数组末尾,需要消耗一定的时间,而LinkedList便可以很轻易地做到。

    5。ArrayList 默认初始容量是10,扩容时扩容它旧容量的1.5倍加1.

  • 相关阅读:
    驰骋工作流引擎2016年第1次组团培训日程
    CCBPM中流程回滚的介绍
    CCBPM流程变更处理解决方案与对策
    CCBPM多表单流程中关于绑定表单的设计步骤
    CCBPM关于工作流引擎取回审批的设计方案与实现过程
    线程池 -实现线程复用
    线程安全 -同步锁机制
    匿名内部类创建线程,简化线程创建代码
    Thread -线程的两种创建方式
    Throwable -抛出异常类与自定义异常类
  • 原文地址:https://www.cnblogs.com/xiamengge/p/7262294.html
Copyright © 2020-2023  润新知