JDK集合之List

一、定义

二、实现

1、ArrayList

1.1、定义

ArrayList是通过列表方式存储数据的集合。它的底层数据结构是数组,且提供了动态调整数组容量的功能ArrayList是线程不安全的,若需要使用线程安全的ArrayList,则可以使用Vector、Collection.synchronizedList()、CopyOrWriteArrayList。

Arrays.asList方法是构造一个固定不能修改的ArrayList,若需要可以修改的,可以使用new ArrayList(Arrays.asList(xxx))

1.2、特性

1.3、原理

(1)ArrayList的2个常用构造方法
A、无参构造方法
  1. public ArrayList() 
    1. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA(DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空数组)
B、有参构造方法
  1.   public ArrayList(int initialCapacity)
    1. if (initialCapacity > 0)
      1. this.elementData = new Object[initialCapacity]
    2. else if (initialCapacity == 0)
      1. this.elementData = EMPTY_ELEMENTDATA(EMPTY_ELEMENTDATA是一个空数组)
    3. else 
      1. throw new IllegalArgumentException("Illegal Capacity: "+
                                                       initialCapacity)
(2)扩容机制

ArrayList的扩容机制主要是通过grow()方法。主要扩容逻辑是:若无参构建ArrayList,第一次扩容时按照10的1.5倍扩容,之后或者有参构造则都按照下面这种方式进行扩容:按照设置的容量*1.5倍进行扩容。

A、grow方法调用过程
  1. grow()
    1. return grow(size + 1)(size表示元素数组中包含的元素个数,size+1表示最小扩容容量)
      1. grow(int minCapacity)
        1. return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));(对旧数组进行扩容)
          1. newCapacity(int minCapacity) 
            1. int oldCapacity = elementData.length;
            2. int newCapacity = oldCapacity + (oldCapacity >> 1)(对旧容量扩容1.5倍)
            3. if (newCapacity - minCapacity <= 0)判断新容量是否小于等于最小扩容容量
              1. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)(无参构建且未扩容)
                1. return Math.max(DEFAULT_CAPACITY, minCapacity);(DEFAULT_CAPACITY为10,返回默认容量和最小容量之间的最大值)
              2. if (minCapacity < 0)(数据类型溢出)
                1. throw new OutOfMemoryError()
              3. return minCapacity(返回最小容量)
            4. return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity: hugeCapacity(minCapacity)(判断新容量是否小于等于数组最大容量,是则直接返回新容量)
              1. hugeCapacity(int minCapacity)(否,新容量大于最大容量则需要继续判断)
                1. if (minCapacity < 0) (数据类型溢出)
                  1. throw new OutOfMemoryError()
                2. return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE: MAX_ARRAY_SIZE(若最小扩容容量大于数组最大容量则返回Integer最大值,否则返回数组最大容量MAX_ARRAY_SIZE为 Integer.MAX_VALUE-8)
B、大体流程
  1. 确定最小扩容容量size+1
  2. 确定旧容量
  3. 计算新容量
  4. 判断新容量是否小于最小扩容量
    1. 是,判断数组容量是否为DEFAULTCAPACITY_EMPTY_ELEMENTDATA
      1. 是,返回默认容量10
    2. 否,判断最小扩容量是否数据溢出
      1. 是,抛异常
      2. 否,返回最小扩容量
  5. 判断新容量是否小于等于数组最大容量
    1. 是,返回新容量
    2. 否,判断最小扩容量是否数据溢出
      1. 是,抛异常
      2. 否,判断最小扩容量是否大于数组最大容量
        1. 是,返回Integer.MAX_VALUE-8
        2. 否,返回数组最大容量
(3)添加元素:add方法

A、add方法调用过程

  1. add(E e)
    1. add(e, elementData, size)
      1. add(E e, Object[] elementData, int s)
        1. if (s == elementData.length)
          1. elementData = grow()(进行扩容)
        2. elementData[s] = e添加元素
        3. size = s + 1
    2. return true
(4)删除元素

迭代删除元素的方式

  • 对源集合进行拷贝,利用迭代器方法对拷贝的列表进行删除操作;
  • 对源集合进行拷贝,利用Stream方式对拷贝的列表进行删除操作;

删除集合中的重复元素: 利用Stream的distinct方法

2、LinkedList

LinkedList是List接口和Queue接口的实现,它是以双向链表的方式存储元素。与ArrayList相比,链表具体更高的灵活性,特别适用于频繁的插入和删除操作。但是,LinkedList由于每个节点都要维护前后元素的节点,所以占用的空间相对ArrayList会耗费空间,可这不是绝对的,由于ArrayList每次都会扩容到原理的1.5倍,所以它占用的空间也是不小的。

三、线程安全的List

1、线程安全的ArrayList

ArrayList是线程不安全的,在jdk1.0版本增加了Vector类,它是线程安全版的ArrayList。它是通过在读写方法上加上synchronized关键字来保证线程安全,且在扩容机制上,ArrayList扩容是容量的1.5倍,而Vector扩容是容量的2倍。但是,由于Vector是通过在读写方法上加上synchronized来保证线程安全的,所以性能较差,不建议使用Vector。也可以利用Collection.synchronizedList()构造一个线程安全的ArrayList。但是也是把所有方法加上synchronized关键字,性能也是较差,不建议使用。CopyOnWriteArrayList是线程安全版的ArrayList,它是的核心是复制一份再进行写入,且会在写数据加锁(可重入锁),读数据又不用加锁。在读多写少的场景可以大大提高数据读写性能。但是若是在读少写多的场景,由于每次写操作都要进行复制,性能和内存开销非常大,如果集合较大,非常容易出现内存溢出的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值