zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    模板 无源汇上下界可行流 loj115
    ICPC2018JiaozuoE Resistors in Parallel 高精度 数论
    hdu 2255 奔小康赚大钱 最佳匹配 KM算法
    ICPC2018Beijing 现场赛D Frog and Portal 构造
    codeforce 1175E Minimal Segment Cover ST表 倍增思想
    ICPC2018Jiaozuo 现场赛H Can You Solve the Harder Problem? 后缀数组 树上差分 ST表 口胡题解
    luogu P1966 火柴排队 树状数组 逆序对 离散化
    luogu P1970 花匠 贪心
    luogu P1967 货车运输 最大生成树 倍增LCA
    luogu P1315 观光公交 贪心
  • 原文地址:https://www.cnblogs.com/xiamengge/p/7262294.html
Copyright © 2011-2022 走看看