zoukankan      html  css  js  c++  java
  • 004-jdk-数据结构-ArrayList、LinkedList

    一、ArrayList概述

      数组集合,无容量限制,非线程安全

      ArrayList、Vector是线性表,使用Object数组作为容器去存储数据的,添加了很多方法维护这个数组,使其容量可以动态增长,极大地提升了开发效率。它们明显的区别是ArrayList是非同步的,Vector是同步的。不用考虑多线程时应使用ArrayList来提升效率。

      ArrayList的基层是数组,实现了通过index直接访问数据

    最佳使用推荐

      数据连续写入,需要根据index进行查找;写入和删除较少的,必须使用有参数的构造,即使超过了也会自动扩展。

    1.1、JDK8 的ArrayList实现

    1)重要的成员变量

      private static final int DEFAULT_CAPACITY = 10;

        默认初始化容量

      transient Object[] elementData; 

        存储arraylist元素的数组缓冲区。arraylist的容量是这个数组缓冲区的长度。任何带有elementdata==defaultcapacity_empty_elementdata的空arraylist将在添加第一个元素时扩展为默认容量

      private static final Object[] EMPTY_ELEMENTDATA = {};

        用于空实例的共享空数组实例。

      private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

        共享空数组实例,用于默认大小的空实例。我们将其与空元素数据区分开来,以了解何时充气添加第一个元素。

    2)构造方法

    构造一、空参数构造,构造初始容量为10的空列表。

    //构造初始容量为10的空列表。
    public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }

      创建一个空的共享数组实例,没有初始化的默认的10,默认的是在第一add时候创建的

    构造二、初始容量构造。按照给点参数构造

        //构造具有指定初始容量的空列表。
        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);
            }
        }
    View Code

      参看代码:initialCapacity 大于0 直接创建指定大小的数组;等于0 创建一个空元素的的共享数组;小于0 会抛出异常

      注意:此处的初始容量initialCapacity,不会影响后续的自动扩展,只是降低添加时候的数据动态扩展以及拷贝,如果添加的数据大于initialCapacity,此时就会自动扩展数组了。

        优化点,如果需要确定添加 20个元素,需要initialCapacity的设置为:20,这样就降低了动态扩展,以及数组的拷贝内存,时间的消耗

    构造三、按照集合迭代器返回元素的顺序构造包含指定集合的元素的列表

        //按照集合迭代器返回元素的顺序构造包含指定集合的元素的列表。
        public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();
            if ((size = elementData.length) != 0) {
                // c.toArray might (incorrectly) not return Object[] (see 6260652)
                if (elementData.getClass() != Object[].class)
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
                // replace with empty array.
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }
    View Code

      将集合创建成数据

    3)常用方法说明

      add(E e):元素末尾插入

        先会执行:ensureCapacityInternal(size + 1); 确定增长因子以及初始化默认数组

        分析:ensureCapacityInternal

          1》当前长度加1,calculateCapacity(elementData, minCapacity) ,内部确定了最小容量minCapacity

          2》调用 ensureExplicitCapacity,如果没有超出范围,什么都不做,超出范围,执行grow

          3》查看grow

        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);
        }

          说明:java中有三种移位运算符

            <<      :     左移运算符,num << 1,相当于num乘以2

            >>      :     右移运算符,num >> 1,相当于num除以2

            >>>    :     无符号右移,忽略符号位,空位都以0补齐

          4》grow主要是,扩展1.5倍的容量,重新拷贝创建一个新数组

      add(int index, E element)

        大部分与上述一致,只是在确定增加mod后,System.arraycopy(elementData, index, elementData, index + 1,size - index);必须重建数组。

      remove(Object o)

        移除,如果找到,确定会重新拷贝数组,删除的元素直接抛弃,等待GC收集即可,与clear一致

      其他方法,没有比较复杂的,不在复述

    二、LInkedList

      采用链表进行存储

      基于双向列表的机制,插入创建一个Entry对象,并切换前后元素引用,非线程安全

      相对于ArrayList,其优势:add,remove较快,因为只需要操作前后元素,而ArrayList需要操作整个列表; get,set较慢以为ArrayList是有序的,LinkedList需要整个遍历

      LinkedList是基于双端链表的List,其内部的实现源于对链表的操作,所以适用于频繁增加、删除的情况;该类不是线程安全的;另外,由于LinkedList实现了Queue接口,所以LinkedList不止有队列的接口,还有栈的接口,可以使用LinkedList作为队列和栈的实现。

    最佳使用推荐

      频繁增加、删除的场景,遍历查找较少的

    2.1、JDK1.8的LinkedList实现

      没有具体特殊的。可自行参看

      

  • 相关阅读:
    iaf——接口自动化测试框架
    性能优化系列
    MVC架构简介及其测试策略
    10种常见的软件架构模式
    软件开发框架分析和架构模式
    安全测试基础&安全测试---AppScan扫描工具
    WEB安全测试要点总结
    大数据Hadoop Hive HBase Spark Storm
    第三方授权方式1
    java-weixin-tools接入微信
  • 原文地址:https://www.cnblogs.com/bjlhx/p/11051956.html
Copyright © 2011-2022 走看看