Java 中 ArrayList 和 LinkedList 有什么区别

news2024/11/24 10:23:07

在Java中,ArrayList和LinkedList是两种常见的集合类。它们都实现了List接口,提供了类似数组的功能,可以存储任意类型的对象。虽然它们都可以实现相同的功能,但是它们的底层实现方式有所不同,因此在性能和用途上也存在一些差异。

在这里插入图片描述

ArrayList

ArrayList是一个基于数组实现的动态数组,它可以自动扩展容量以容纳新的元素。在ArrayList中,元素存储在一个Object数组中,可以通过索引访问数组中的元素。

底层原理

ArrayList底层使用数组实现,每个ArrayList实例都包含一个Object类型的数组elementData,用于存储元素。当ArrayList中的元素数量超过数组容量时,ArrayList会自动扩容,创建一个新的数组,并将原数组中的元素复制到新数组中。

private transient Object[] elementData;

在ArrayList中,添加元素的操作可以分为两种情况:

  • 如果数组容量足够,直接将元素添加到数组末尾。
  • 如果数组容量不足,需要先对数组进行扩容,然后将元素添加到数组末尾。
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

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

在ArrayList中,删除元素的操作可以分为两种情况:

  • 如果要删除的元素在数组中间,需要将后续的元素向前移动,覆盖要删除的元素。
  • 如果要删除的元素在数组末尾,直接将数组长度减一即可。
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0) {
        System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
    }
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

特点

  • ArrayList是一个基于数组实现的动态数组,可以自动扩容以容纳新的元素。
  • 在ArrayList中,元素可以通过索引访问,因此随机访问效率较高。
  • 在ArrayList中,插入和删除操作可能需要移动后续的元素,因此效率较低。

源码

ArrayList的源码可以在JDK中找到,位于java.util包中。

LinkedList

LinkedList是一个基于链表实现的双向链表,它可以动态地添加、删除元素。在LinkedList中,元素存储在一个节点(Node)中,每个节点包含一个元素和前后指针。

底层原理

LinkedList底层使用双向链表实现,每个LinkedList实例都包含一个Node类型的first和last节点,用于表示链表的头和尾。

java

Copy

private transient Node<E> first;
private transient Node<E> last;

在LinkedList中,添加元素的操作可以分为三种情况:

  • 如果链表为空,将新节点设置为first和last节点。
  • 如果要添加的元素在链表头部,将新节点设置为first节点,并将原first节点作为新节点的后继。
  • 如果要添加的元素在链表尾部,将新节点设置为last节点,并将原last节点作为新节点的前驱。
public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

在LinkedList中,删除元素的操作可以分为三种情况:

  • 如果要删除的元素是first节点,将first节点设置为原first节点的后继。
  • 如果要删除的元素是last节点,将last节点设置为原last节点的前驱。
  • 如果要删除的元素在链表中间,将要删除的节点的前驱和后继节点连接起来,然后将要删除的节点的前驱和后继节点分别指向要删除节点的前驱和后继节点。
public E remove(int index) {
    checkElementIndex(index);
    return unlink(node(index));
}

E unlink(Node<E> x) {
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;

    if (prev == null) {
        first = next;
    } else {
        prev.next = next;
        x.prev = null;
    }

    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }

    x.item = null;
    size--;
    modCount++;
    return element;
}

特点

  • LinkedList是一个基于链表实现的双向链表,可以动态地添加、删除元素。
  • 在LinkedList中,元素不能通过索引访问,因此随机访问效率较低。
  • 在LinkedList中,插入和删除操作只需要改变相邻节点的指针,因此效率较高。

源码

LinkedList的源码可以在JDK中找到,位于java.util包中。

ArrayList和LinkedList的比较

从底层实现上来看,ArrayList和LinkedList有以下区别:

  • ArrayList底层使用数组实现,LinkedList底层使用链表实现。
  • 在ArrayList中,元素可以通过索引访问,因此随机访问效率较高,但是插入和删除操作效率较低。在LinkedList中,元素不能通过索引访问,因此随机访问效率较低,但是插入和删除操作效率较高。
  • 在ArrayList中,添加和删除操作需要移动后续的元素,因此效率较低。在LinkedList中,添加和删除操作只需要改变相邻节点的指针,因此效率较高。
  • 在ArrayList中,扩容时需要创建一个新的数组,并将原数组中的元素复制到新数组中,效率较低。在LinkedList中,不需要扩容,因为链表可以动态地添加、删除节点。

由于ArrayList和LinkedList的底层实现方式不同,因此它们适用的场景也不同:

  • 如果需要频繁访问集合中的元素,并且集合的大小不会经常改变,选择ArrayList会更加合适,因为ArrayList可以通过索引快速访问元素,效率较高。
  • 如果需要频繁添加、删除集合中的元素,选择LinkedList会更加合适,因为LinkedList可以快速地添加、删除节点,效率较高。

总结

ArrayList和LinkedList是Java中常见的集合类,它们都实现了List接口,提供了类似数组的功能,可以存储任意类型的对象。ArrayList底层使用数组实现,LinkedList底层使用链表实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/526421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

dom4j解析XML文件

主要为了讲解Mybatis中如何用dom4j解析XML,这里当作dom4j解析.XML文件的练习 引入mybatis配置文件和一个.xml文件 都是.xml <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN…

【C++】| 04——STL | 容器_vector

系列文章目录 【C】| 01——泛型编程 | 模板 【C】| 02——STL | 初识 【C】| 03——STL | 迭代器 【C】| 04——STL | 容器_vector 文章目录 1. vector容器2. vector库2.1 迭代器相关函数2.1 ww 1. vector容器 vector 与 动态数组 相似&#xff0c;可以自动调节自身大小。元素…

基于SpringBoot的美容院管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SpringBoot 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录 一、项目简介 二、系…

Windows10中英文切换按钮消失?一招解决

目录 问题场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 1. 打开设置&#xff0c;选择时间和语言 2. 进入日期时间设置 3. 进入高级键盘设置 4. 勾选这个勾选框&#xff0c;问题解决 问题场景&#xff1a; 博主玩道德与法治V在线模式时&#…

BGP防环,路由反射器,BGP联盟

数据的出口是路由的入口 ospf内部&#xff1a;10 ospf外部&#xff1a;150 静态路由&#xff1a;60 RIP&#xff1a;100 BGP&#xff1a;255 当下一跳是0.0.0.0 表示的是自己 display bgp peer //查看bgp邻居表 display bgp routing-table //查看bgp数据库 display i…

WPF MaterialDesign 初学项目实战(3)动态侧边栏

其他文章 WPF MaterialDesign 初学项目实战&#xff08;0&#xff09;:github 项目Demo运行 WPF MaterialDesign 初学项目实战&#xff08;1&#xff09;首页搭建 WPF MaterialDesign 初学项目实战&#xff08;2&#xff09;首页导航栏样式 创建侧边栏实体类 新建MenuBar文件…

Python动物图像分割API简单调用实例演示,阿里达摩院视觉智能开放平台使用步骤

阿里云视觉智能开放平台 - 动物分割 效果图演示平台入口创建获取密钥本地图片转 URL 与密钥测试代码调用演示语义分割知识拓展阿里云达摩院智能视觉开放平台 效果图演示 调用本地图片处理后可以直接保存到本地&#xff0c;右边就是分割好的效果图&#xff0c;可以看到分割的效…

基于卷积的图像分类识别(五):ResNet ResNeXt

系列文章目录 本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;MobileN…

C语言实现扫雷

总有一天你要一个人在暗夜中&#xff0c;向那座桥走过去 目录 一、文件及其对应代码 1.test.c 2.game.c 3.game.h 二、数组创建解析 1.创建两个数组的原因 2.预设数组较大的原因 三、计算周围雷的个数 四、向外扩展并延伸判断 扫雷游戏&#xff0c;相信大家都玩过&am…

【c++】图解类和对象(上)

类和对象&#xff08;上&#xff09; 文章目录 类和对象&#xff08;上&#xff09;一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装1.访问限定符2.封装 五、类的作用域六、类的实例化七、类对象模型八、this指针总结 一、面向过程和面向对象…

Mysql中select语句的执行流程?

Mysql中select语句的执行流程&#xff1f; 答&#xff1a; SELECT 语句的执行过程为&#xff1a;连接、查询缓存、a词法分析&#xff0c;语法分析&#xff0c;语义分析&#xff0c;构造执行树&#xff0c;生成执行计划、执行器执行计划&#xff0c;下面开始梳理一次完整的查询…

【MySQL】视图,事务、隔离级别

视图--虚表&#xff0c;不在数据库中存放数据&#xff0c;数据源于基本表。 为什么要使用视图 简化复杂的sql操作&#xff0c;在编写查询后&#xff0c;可以方便的重用它而不必知道它的查询细节。重复使用该sql语句。使用表的组成部分而不是整个表。保护数据&#xff0c;可以给…

vscode编译的时候:未定义标识符 thread

vscode编译的时候&#xff1a;未定义标识符 thread thread’ was not declared in this scope" 未定义标识符 thread 原因 MinGW GCC当前仍缺少标准C 11线程类的实现。 对于跨平台线程实现&#xff0c;GCC标准库依赖于gthreads / pthreads库。如果该库不可用&#xf…

手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(上篇)

1. 前言 说起RNN和LSTM&#xff0c;就绕不过Sepp Hochreiter 1997年的开山大作 Long Short-term Memory。奈何这篇文章写的实在是太劝退&#xff0c;整篇论文就2张图&#xff0c;网上很多介绍LSTM的文章都对这个模型反向传播的部分避重就轻&#xff0c;更少见&#xff08;反正…

2023/5/14学习总结

这道题我们可以看到数据范围很小 &#xff0c;所以可以使用暴力枚举&#xff0c;将所有可以组成长方形的长宽全遍历一遍&#xff0c;同时要满足这个长方形里没有障碍物的条件&#xff0c;取得周长最大值 #include<bits/stdc.h> using namespace std; typedef long long …

JavaSE基础(六)—— 面向对象、封装、对象内存图、成员变量和局部变量区别

目录 一、面向对象对象介绍 1. 面向对象的重点学习什么 二、设计对象并使用 1. 设计类&#xff0c;创建对象并使用 1.1 如何得到对象 1.2 如何使用对象 2. 定义类的几个补充注意事项 2.1 对象的成员变量的默认值规则 三、对象内存图 1. 多个对象内存图 2. 两个变量指…

Springboot +Flowable,流程表单应用之静态表单

一.简介 整体上来说&#xff0c;我们可以将Flowable 的表单分为三种不同的类型&#xff1a; 动态表单 这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息&#xff0c;不过不能定义完整的表单页面。外置表单 外置表单我们只需要定义一下表单的 k…

生命周期、数据共享、ref引用、购物车案例

生命周期&数据共享 1.组件的生命周期2.组件之间的数据共享3.ref 引用4.购物车案例 1.组件的生命周期 生命周期 & 生命周期函数 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 生命…

chatGPT提问,BGP内容

ChatGPT提问&#xff1a;提问框架 背景角色任务要求 动态路由&#xff1a;内部网关协议&#xff1a;如RIP ISIS OSPF 在同一个公司内部运行的路由协议 外部网关协议&#xff1a;如 BGP 在不同公司之间运行的路由协议 AS&#xff1a;自治系统 每个自治系统都有唯一的…

动态组件、插槽、自定义指令、Eslint和prettierrc配置、axios全局挂载

动态组件、插槽、自定义指令、Eslint和prettierrc配置、axios全局挂载 动态组件插槽体验插槽的基础用法作用域插槽 自定义指令Eslint和prettierrc配置prettierrc axios全局挂载 动态组件 动态组件指的是动态切换组件的显示与隐藏。 如何实现动态组件渲染 vue 提供了一个内置的…