• ArrayList 与 LinkedList的区别


    今天查看源码,分析一下两者的异同。外加阐述内部类。

    内部类参考官方文档,地址如下:

    https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

    本文思路是从两者的构造函数着手,之后是add()分析。

    1.构造函数

     1 public class Test {
     2 
    // 下面两行不多说,就是创建List,这时注意一点,在构造函数中,尽量指定集合的大小。你可能会问,不指定的话,不是会有默认的size吗?完全正确。
    // 但是当程序指定默认的size后,当集合变大需要扩容的时候,会阻碍一部分性能,所以如果能够预知list的size,尽量指定合理的大小。 3 List<String> aList = new ArrayList<String>();
    // List<String> aList = new ArrayList<String>(16);
    4 List<String> bList = new LinkedList<String>();
    // List<String> bList = new LinkedList<String>(16);
    5 } 6 7 /** 8 * Constructs an empty list with the specified initial capacity. 9 * 10 * @param initialCapacity the initial capacity of the list 11 * @throws IllegalArgumentException if the specified initial capacity 12 * is negative 13 */
    // 带有size大小的初期化方法,没什么可说的。判断size大小
    14 public ArrayList(int initialCapacity) { 15 if (initialCapacity > 0) { 16 this.elementData = new Object[initialCapacity]; 17 } else if (initialCapacity == 0) { 18 this.elementData = EMPTY_ELEMENTDATA; 19 } else { 20 throw new IllegalArgumentException("Illegal Capacity: "+ 21 initialCapacity); 22 } 23 } 24 25 /** 26 * Constructs an empty list with an initial capacity of ten. 27 */
    // 默认构造器
    28 public ArrayList() { 29 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 30 }


           /**
         * Constructs an empty list.
         */
        public LinkedList() {
        }

    2. ArrayList的add()方法

     1     /**
     2      * Appends the specified element to the end of this list.
     3      *
     4      * @param e element to be appended to this list
     5      * @return <tt>true</tt> (as specified by {@link Collection#add})
     6      */
     7     public boolean add(E e) {
     8         // 扩容
     9         ensureCapacityInternal(size + 1);  // Increments modCount!!
    10         // 在最后位置赋值
    11         elementData[size++] = e;
    12         return true;
    13     }
     1 private void ensureCapacityInternal(int minCapacity) {
     2         // 判断list是否为空,如果为空,则为list指定默认容量,DEFAULT_CAPACITY的值是10
     3         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
     4             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
     5         }
     6 
     7         // 进行扩容
     8         ensureExplicitCapacity(minCapacity);
     9     }
    10 
    11     private void ensureExplicitCapacity(int minCapacity) {
    // 这个变量记录list结构扩容的次数,更具体的用处是什么,稍后研究。如果有想法的朋友,一起探讨
    12 modCount++; 13 14 // overflow-conscious code 15 if (minCapacity - elementData.length > 0) 16 grow(minCapacity); 17 }
     1 /**
     2      * Increases the capacity to ensure that it can hold at least the
     3      * number of elements specified by the minimum capacity argument.
     4      *
     5      * @param minCapacity the desired minimum capacity
     6      */
     7     private void grow(int minCapacity) {
     8         // overflow-conscious code
     9         int oldCapacity = elementData.length;
    10         int newCapacity = oldCapacity + (oldCapacity >> 1);
    11         if (newCapacity - minCapacity < 0)
    12             newCapacity = minCapacity;
    13         if (newCapacity - MAX_ARRAY_SIZE > 0)
    14             newCapacity = hugeCapacity(minCapacity);
    15         // minCapacity is usually close to size, so this is a win:
    // 大家在这里可以按到ArrayList使用的是数组结构,当元素增加或减少时会将数组进行复制,因此查询速度快,增加或删除时,相对较慢。
    16 elementData = Arrays.copyOf(elementData, newCapacity); 17 } 18 19 private static int hugeCapacity(int minCapacity) { 20 if (minCapacity < 0) // overflow 21 throw new OutOfMemoryError(); 22 return (minCapacity > MAX_ARRAY_SIZE) ? 23 Integer.MAX_VALUE : 24 MAX_ARRAY_SIZE; 25 }

    3. LinkedList的add()方法

     1     public boolean add(E e) {
     2         linkLast(e);
     3         return true;
     4     }
     5 
     6 /**
     7      * Links e as last element.
     8      */
     9     void linkLast(E e) {
    10         final Node<E> l = last;
    // 封装了数据e的新节点
    11 final Node<E> newNode = new Node<>(l, e, null); 12 last = newNode;
    // 如果是null表明链表中数据为空,那么将新节点设置为首节点,如果不为空,则增加的最后一个节点。
    // 因此在查询的时候,需要从头一直查到最后一个,效率较慢,但是面对增加删除时,只需更该其中的关联的前后节点,不必进行数组的复制,因此性能得以提升。
    13 if (l == null) 14 first = newNode; 15 else 16 l.next = newNode; 17 size++; 18 modCount++; 19 }

    我们在查看Node<E>这个类时,会发现它是个静态内部类。

     1 private static class Node<E> {
     2         E item;
     3         Node<E> next;
     4         Node<E> prev;
     5 
     6         Node(Node<E> prev, E element, Node<E> next) {
     7             this.item = element;
     8             this.next = next;
     9             this.prev = prev;
    10         }
    11     }

    内部类有什么作用,以前为什么会有静态内部类和非静态内部类呢?

    我呢就不做搬运工了,在此呢推荐个官方文章,https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

    里面详细阐述了内部类的分类,使用的好处等。

  • 相关阅读:
    Windows RC版、RTM版、OEM版、RTL版、VOL版的区别
    jQuery MiniUI开发系列之:创建组件对象
    Mobile Web 调试指南(2):远程调试
    Using the viewport meta tag to control layout on mobile browsers
    鼠标滚轮事件MouseWheel
    photoshop基础
    10个jQuery插件分享
    Centos 安装nodejs
    Centos 安装.NET CORE 3.1
    Centos 安装nginx
  • 原文地址:https://www.cnblogs.com/lihao007/p/8595952.html
Copyright © 2020-2023  润新知