ArrayList 和LinkedList

news2024/12/29 11:52:13

目录

  • ArrayList
      • add自动扩容
      • ArrayList的remove()方法
      • 查找 indexof
  • LinkedList
      • LinkedList的add方法
      • LinkedList的remove方法
      • 查找 indexof
    • arraylist和linkedlist的区别

ArrayList

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。
在这里插入图片描述

add自动扩容

每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容,以满足添加数据的需求:

 public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }
    
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, 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);
    }

数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍(>> 1)。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。

ArrayList的remove()方法

删除操作是add()操作的逆过程,需要将删除点之后的元素向前移动一个位置。需要注意的是为了让GC起作用,必须显式的为最后一个位置赋null值。

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; //清除该位置的引用,让GC起作用
    return oldValue;
}

查找 indexof

获取元素的第一次出现的index:

public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

LinkedList

LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。不过,关于栈或队列,现在的首选是ArrayDeque,它有着比LinkedList(当作栈或队列使用时)有着更好的性能。

 transient int size = 0;
 transient Node<E> first;
 transient Node<E> last;
 private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

LinkedList的add方法

add()方法有两个版本,一个是add(E e),该方法在LinkedList的末尾插入元素,因为有last指向链表末尾,在末尾插入元素的花费是常数时间。只需要简单修改几个相关引用即可;另一个是add(int index, E element),该方法是在指定下表处插入元素,需要先通过线性查找找到具体位置,然后修改相关引用完成插入操作。

public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    /**
     * Links e as last element.
     */
    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的remove方法

删除元素 - 指的是删除第一次出现的这个元素, 如果没有这个元素,则返回false;判断的依据是equals方法, 如果equals,则直接unlink这个node;由于LinkedList可存放null元素,故也可以删除第一次出现null的元素。
我们可以给出一些示例比如LinkedList存在6,7,8三个元素,实现即是:

  1. 前一个节点的变化:6的下一个节点指向8,且断开7的上一个节点
  2. 后一个节点的变化:8的上一个节点指向6,且断开7的下一个节点
 public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }
 /**
     * 从链表中移除非空节点x,并返回该节点存储的元素。
     * @param x 需要被移除的非空节点
     * @return 被移除节点存储的元素
     */
 E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;

        if (prev == null) {
            first = next;
        } else {
        // 将前一个节点的next指针指向当前节点的下一个节点
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
         // 将下一个节点的prev指针指向当前节点的前一个节点
            next.prev = prev;
            x.next = null;
        }
// // 清空节点的元素,以便垃圾回收
        x.item = null;
        // 更新链表大小
        size--;
        modCount++;
        return element;
    }

查找 indexof

在链表中查找指定元素首次出现的索引位置。如果链表中不存在该元素,则返回-1。

 public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

arraylist和linkedlist的区别

ArrayList和LinkedList在数据结构、性能特点以及内存空间等方面存在显著差异。

  1. 数据结构:ArrayList是基于动态数组实现的,而LinkedList是基于双向链表实现的。这导致它们在功能上和使用方式上有所不同。
  2. 随机访问速度:由于ArrayList基于数组,可以直接通过数组下标以常数时间O(1)来访问元素,因此它在随机访问集合元素时性能更优。相比之下,LinkedList需要从头或尾遍历节点来找到特定位置的元素,这使得随机访问的时间复杂度为O(n),较慢于ArrayList。
  3. 插入和删除操作:LinkedList在插入和删除操作上具有优势,因为它只需要改变节点指针,不需要移动其他元素。其插入和删除的时间复杂度为O(1),而ArrayList在插入和删除时需要移动数组中的其他元素,时间复杂度为O(n)。
  4. 内存空间:LinkedList的每个元素需要额外的空间存储前后节点的地址信息,因此它比ArrayList占用更多的内存空间。
  5. 线程安全性:ArrayList不是线程安全的,而Vector是它的同步版本,是线程安全的。相反,LinkedList也不是线程安全的。
  6. 功能多样性:除了作为List接口的实现类外,LinkedList还实现了Deque接口,可以作为栈、队列和双端队列使用,因此在功能上更为多样。

总的来说,如果应用程序对数据的随机访问需求较多,则ArrayList的性能较优;而如果应用程序中插入和删除操作更为频繁,则LinkedList可能更加适合。选择ArrayList还是LinkedList取决于具体的应用场景。

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

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

相关文章

恒峰智慧科技-太阳能语音警示杆:节能环保新时代的标配!

随着社会的发展和人们对环境保护意识的不断提高&#xff0c;节能环保已经成为了新时代的标配。在这个大背景下&#xff0c;太阳能语音警示杆应运而生&#xff0c;为森林防火工作提供了有力的支持。太阳能语音警示杆是一种集太阳能发电、语音播报、红蓝警示灯于一体的多功能设备…

【解决NodeJS项目无法在IDEA中调试的问题】使用JetBrains IDEA 2023 调试nodejs项目

项目采用Ant Design Pro React&#xff0c;使用前后端分离开发方式&#xff0c;后端可以很容易的打断点调试&#xff0c;但是前端通过网页进行调试&#xff0c;在IDEA中加了调试断点&#xff0c;但是没有什么用处。 解决方案如下&#xff1a; 点击新建运行配置 新建JavaScrip…

比亚迪唐EV和唐DM-p荣耀版上市,成为新能源汽车市场中的佼佼者!

随着环保理念的深入人心&#xff0c;新能源汽车市场正迎来前所未有的发展机遇。在这个变革的浪潮中&#xff0c;唐EV和唐DM-p荣耀版的上市无疑为市场注入了新的活力。它们凭借先进的技术、卓越的性能以及豪华配置&#xff0c;成为了新能源汽车市场中的佼佼者。然而&#xff0c;…

银行买的黄金怎么卖出去?了解黄金交易的步骤和注意事项

黄金一直以来都是备受投资者关注的贵金属之一。银行提供了购买黄金的机会&#xff0c;但投资者也需要了解如何卖出银行买的黄金。 选择适合的购买方式 投资者可以通过多种途径购买黄金&#xff0c;其中包括银行提供的黄金交易服务。银行买黄金的方式可以是通过黄金交易账户、黄…

从C向C++14——STL初识及函数对象

一.STL初识 1.STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生了ST…

MPC的横向控制与算法仿真实现

文章目录 1. 引言2. 模型预测控制&#xff08;MPC&#xff09;2.1 基础知识2.2 MPC的整体流程2.3 MPC的设计求解 3. 车辆运动学MPC设计4. 算法和仿真实现 1. 引言 随着智能交通系统和自动驾驶技术的发展&#xff0c;车辆的横向控制成为了研究的热点。横向控制指的是对车辆在行…

《html自用使用指南》--基于w3School实践

1.基础标签 文本输入时&#xff0c;在编辑器中的换行&#xff0c;多个空格&#xff0c;都被编辑器看作一个空格 <p> 这个段落 在源代码 中 包含 许多行 但是 浏览器 忽略了 它们。 </p>结果&#xff1a;这个段落 在源代码 中 包含 许多行 但是 浏览器…

机器学习中常见的数据分析,处理方式(以泰坦尼克号为例)

数据分析 读取数据查看数据各个参数信息查看有无空值如何填充空值一些特殊字段如何处理读取数据查看数据中的参数信息实操具体问题具体分析年龄问题 重新划分数据集如何删除含有空白值的行根据条件删除一些行查看特征和标签的相关性 读取数据 查看数据各个参数信息 查看有无空…

Python Tiler库:创建可视化网格布局的利器

更多Python学习内容&#xff1a;ipengtao.com Tiler是一个Python库&#xff0c;用于创建各种类型的网格布局&#xff0c;包括等宽/等高布局、自定义大小布局、响应式布局等。本文将深入介绍Tiler库的功能、用法以及示例代码&#xff0c;帮助读者全面了解并灵活应用该库。 安装和…

主打国产算力 广州市通用人工智能公共算力中心项目签约

4月9日&#xff0c;第十届广州国际投资年会期间&#xff0c;企商在线&#xff08;北京&#xff09;数据技术股份有限公司与广州市增城区政府就“广州市通用人工智能公共算力中心”项目进行签约。 该项目由广州市增城区人民政府发起&#xff0c;企商在线承建。项目拟建成中国最…

【Linux】实现一个进度条

我们之前也学了gcc/vim/make和makefile&#xff0c;那么我们就用它们实现一个进度条。 在实现这个进度条之前&#xff0c;我们要先简单了解一下缓冲区和回车和换行的区别 缓冲区其实就是一块内存空间&#xff0c;我们先看这样一段代码 它的现象是先立马打印&#xff0c;三秒后程…

centos7.6上安装mysql7.6 完整过程

安装过程&#xff1a; 参考&#xff1a;https://blog.csdn.net/qq_45103475/article/details/123151050 查找mysql [rootbogon ~]# whereis mysql mysql: /usr/lib64/mysql /usr/share/mysql 删除目录 [rootbogon ~]# rm -rf /usr/lib64/mysql [rootbogon ~]# whereis mysql m…

ClickHouse 高可用之副本

文章目录 ClickHouse 副本支持副本的引擎配置高可用副本副本应用1.副本表概述2.创建副本表3.写入模拟数据4.副本验证 扩展 —— 在 Zookeeper 中查看副本表信息 ClickHouse 副本 ClickHouse 通过副本机制&#xff0c;可以将数据拷贝存储在不同的节点上。这样&#xff0c;如果一…

python 如何判断两个字典是否相等

Python 字典的 cmp() 函数用于比较两个字典元素。 语法 cmp()方法语法&#xff1a; cmp(dict1, dict2)参数 dict1 -- 比较的字典。 dict2 -- 比较的字典。 返回值 如果两个字典的元素相同返回0&#xff0c;如果字典dict1大于字典dict2返回1&#xff0c;如果字典dict1小于…

白酒:香型对白酒品质的影响与消费者偏好

云仓酒庄的豪迈白酒认为香型对白酒品质的影响与消费者偏好是值得探讨的话题。香型作为白酒品质的重要因素之一&#xff0c;对白酒的口感、风味和品质产生着深远的影响。同时&#xff0c;消费者的偏好也是决定香型选择的重要因素之一。 首先&#xff0c;香型对白酒品质的影响是不…

Qt中的 tableView 设置 二进制 十六进制 序号表头

二 进制序号 因为QTableView的垂直表头并不支持使用委托来自定义。 相反&#xff0c;可以通过将自定义的QWidget作为QHeaderView的标签来实现这一目标。 代码&#xff1a; #include <QApplication> #include <QMainWindow> #include <QVBoxLayout> #include …

【管理咨询宝藏85】MBB物流战略规划及实施落地项目报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏85】MBB物流战略规划及实施落地项目报告 【格式】PDF版本 【关键词】战略规划、MBB、麦肯锡 【核心观点】 - 全面进行小件包裹业务实施方案的细…

编程基础“四大件”

基础四大件包括&#xff1a;数据结构和算法,计算机网络,操作系统,设计模式 这跟学什么编程语言,后续从事什么编程方向均无关&#xff0c;只要做编程开发&#xff0c;这四个计算机基础就无法避开。可以这么说&#xff0c;这基础四大件真的比编程语言重要&#xff01;&#xff0…

如何定制企业PIA问卷?

前言 大家好&#xff0c;欢迎关注用九智汇。 作为国内专业的数据合规与隐私保护工具科技服务商&#xff0c;我们近几年为多个客户提供了企业级数据合规与隐私保护体系的系统落地解决方案&#xff0c;这些客户覆盖了智能网联汽车、互联网医疗、智能硬件、金融、新零售等多个行…

【Vue】常见的七大属性(描述+案例)

一、前言 最近&#xff0c;因为项目需要自己就去学习了一下Vue的相关知识&#xff0c;自己花了几天&#xff0c;结合官方文档和相应的视频学习了一下Vue,了解了Vue大概的一些属性&#xff0c;方法&#xff0c;特点等。接下来博主会将自己学习的相关内容通过博客的形式进行记录…