深入浅出分析 Collection 中的 List 接口(上)

简介: 在前面的文章集合系列中,我相信大部分朋友对 Java 容器整体架构都有了初步的了解,那么本文主要是想详细的介绍以下 List 接口实现类之间的区别!

01、List 简介

List 的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址与索引对应。

以下是 List 集合简易架构图

37.jpg

由图中的继承关系,可以知道,ArrayList、LinkedList、Vector、Stack 都是List 的四个实现类。

  • AbstractCollection 是一个抽象类,它唯一实现 Collection 接口的类。AbstractCollection 主要实现了 toArray()、toArray(T[] a)、remove() 等方法。
  • AbstractList 也是一个抽象类,它继承于 AbstractCollection。AbstractList 实现 List 接口中除 size()、get(int location) 之外的函数,比如特定迭代器 ListIterator。
  • AbstractSequentialList 是一个抽象类,它继承于 AbstractList。AbstractSequentialList 实现了“链表中,根据 index 索引值操作链表的全部函数”。
  • ArrayList 是一个动态数组,它由数组实现。随机访问效率高,随机插入、随机删除效率低。
  • LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList 随机访问效率低,但随机插入、随机删除效率高。
  • Vector 也是一个动态数组,和 ArrayList 一样,也是由数组实现。但是ArrayList 是非线程安全的,而 Vector 是线程安全的。
  • Stack 是栈,它继承于 Vector。它的特性是:先进后出(FILO, First In Last Out)。

下面对各个实现类进行方法剖析!

02、ArrayList

ArrayList 实现了 List 接口,也是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入 null 元素,底层通过数组实现。除该类未实现同步外,其余跟 Vector 大致相同。

在 Java1.5 之后,集合还提供了泛型,泛型只是编译器提供的语法糖,方便编程,对程序不会有实质的影响。因为所有的类都默认继承至 Object,所以这里的数组是一个 Object 数组,以便能够容纳任何类型的对象。


38.jpg

2.1、get 方法

get() 方法同样很简单,先判断传入的下标是否越界,再获取指定元素。

public E get(int index) {
        rangeCheck(index);
        return elementData(index);
}
/**
 * 检查传入的index是否越界
 */
private void rangeCheck(int index) {
        if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

2.2、set 方法

set() 方法也非常简单,直接对数组的指定位置赋值即可。

public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
}

2.3、add 方法

ArrayList 添加元素有两个方法,一个是 add(E e),另一个是 add(int index, E e)。这两个方法都是向容器中添加新元素,可能会出现容量(capacity)不足,因此在添加元素之前,都需要进行剩余空间检查,如果需要则自动扩容。扩容操作最终是通过 grow() 方法完成的。

39.jpg

grow方法实现

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//原来的1.5倍
        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);
}

添加元素还有另外一个 addAll() 方法,addAll() 方法能够一次添加多个元素,根据位置不同也有两个方法,一个是在末尾添加的 addAll(Collection<? extends E> c)方法,一个是从指定位置开始插入的 addAll(int index, Collection<? extends E> c)方法。

不同点:addAll() 的时间复杂度不仅跟插入元素的多少有关,也跟插入的位置相关,时间复杂度是线性增长!

相关文章
|
2月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
36 5
|
5月前
|
存储 Java 测试技术
滚雪球学Java(57):解密Java中List接口底层实现原理
【6月更文挑战第11天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
43 2
滚雪球学Java(57):解密Java中List接口底层实现原理
|
4月前
|
文字识别 Java
文本,文字识别07,SpringBoot服务开发-入参和返回值,编写接口的时候,要注意识别的文字返回的是多行,因此必须是List集合,Bean层,及实体类的搭建
文本,文字识别07,SpringBoot服务开发-入参和返回值,编写接口的时候,要注意识别的文字返回的是多行,因此必须是List集合,Bean层,及实体类的搭建
|
4月前
|
前端开发
若依修改,配置了一个接口路径出现了,如何放通接口{ “msg“: “请求访问:/code/list,认证失败,无法访问系统资源“, “code“: 401}
若依修改,配置了一个接口路径出现了,如何放通接口{ “msg“: “请求访问:/code/list,认证失败,无法访问系统资源“, “code“: 401}
|
6月前
|
存储 安全 Java
Java的List、Set、Queue等接口及其实现类的技术性文章
Java的List、Set、Queue等接口及其实现类的技术性文章
37 1
|
6月前
|
存储 安全 Java
Java list set map等接口及其实现类
Java list set map等接口及其实现类
|
6月前
|
存储 算法 C语言
从C语言到C++_16(list的介绍和常用接口函数)
从C语言到C++_16(list的介绍和常用接口函数)
61 0
|
5月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
934 1
|
4月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
4月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。

热门文章

最新文章

下一篇
无影云桌面