LinkedList详解

news2025/2/28 20:24:18

介绍

众所周知ArrayList底层数据结构是数组,但是数组有个缺点,虽然查询快,但是增删改会慢因为数组是在连续的位置上面储存对象的应用。当我们删除某一个元素的时候在他后面的元素的索引都会左移,导致开销会很大。所以LinkedList应运而生。

LinkedList底层数据结构

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表和双向链表。
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
在这里插入图片描述
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。
在这里插入图片描述
因为LinkedList 采用的是双向链表所以LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。

应用场景

1.你需要通过循环迭代来访问列表中的某些元素。
2.需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

类继承关系

在这里插入图片描述

应用案例

案例抄自https://www.runoob.com/java/java-linkedlist.htm

添加元素

public class Test {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites);
    }
}

在列表开头添加元素

public class Test {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        // 使用 addFirst() 在头部添加元素
        sites.addFirst("Wiki");
        System.out.println(sites);
    }
}

在列表结尾添加元素:

public class Test {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        // 使用 addLast() 在尾部添加元素
        sites.addLast("Wiki");
        System.out.println(sites);
    }
}

列表开头移除元素

public class Test {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 removeFirst() 移除头部元素
        sites.removeFirst();
        System.out.println(sites);
    }
}

在列表结尾移除元素

public class Test {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 removeLast() 移除尾部元素
        sites.removeLast();
        System.out.println(sites);
    }
}

获取列表头部元素

    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 getFirst() 获取头部元素
        System.out.println(sites.getFirst());
    }

获取列表结尾的元素

 public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 getLast() 获取尾部元素
        System.out.println(sites.getLast());
    }

循环获取元素

public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        for (int size = sites.size(), i = 0; i < size; i++) {
            System.out.println(sites.get(i));
        }
    }

常用方法

在这里插入图片描述
在这里插入图片描述

底层原理

无参构造器

    public LinkedList() {
    }

add

    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    void linkLast(E e) {
        //获取最后一个节点的node (如果刚开始没添加数据的时候last是空)
        final Node<E> l = last;
        //构建一个node 节点
        final Node<E> newNode = new Node<>(l, e, null);
        //把刚创建的node节点赋值到最后一个节点
        last = newNode;
        //如果l == null 表示链表上还没有数据
        if (l == null)
            //把刚创建的节点当成头节点
            first = newNode;
        else
         //因为l != null 肯定链表上已经有数据了则将刚创建的节点绑定在l节点的下一个节点
            l.next = newNode;
        size++;
        modCount++;
    }

创建Node节点

    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;
            //当前节点的next 节点因为当前节点是新构建的节点他的next节点肯定是空
            this.next = next;
            //指向当前节点的前一个节点
            this.prev = prev;
        }
    }

get(int index)

    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }

checkElementIndex(int index)

校验是否超过最大长度限制

    private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

获取元素

判断index在链表的哪边。
遍历查找index或者size-index次,找出对应节点。
这里我们知道,相比于数组的直接索引获取,遍历获取节点效率并不高

    Node<E> node(int index) {
        // assert isElementIndex(index);
         
        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

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

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

相关文章

Linux系统下交叉编译工具的安装实现

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用Linux系统下的交叉编译工具链的方法。 目录 第一:交叉编译工具链基本简介 ​第二&#xff1a;交叉编译工具安装方法 ​第三&#xff1a;安装相关库 ​第四&#xff1a;交叉编译工具验证 第一:交叉编译工具链基…

0100 蓝桥杯真题03

import java.util.Scanner; /* * 题目描述 * 如下图所示&#xff0c;3 x 3 的格子中填写了一些整数。 --*---- |10* 1|52| --****-- |20|30* 1| *******-- | 1| 2| 3| ------ *我们沿着图中的星号线剪开&#xf…

【Redis-04】Redis两种持久化方式(RDB和AOF)

Redis是基于内存的数据结构服务器&#xff0c;保存了大量的键值对数据&#xff0c;所以持久化到磁盘是非常必要的&#xff0c;Redis提供了两种持久化的方式&#xff0c;分别是RDB和AOF。下面我们看下这两种持久化方式的具体实现原理。 1.RDB持久化 首先&#xff0c;RDB持久化方…

Mysql基础

Mysql基础1. 数据库相关概念1.1 数据库1.2 数据库管理系统1.3 常见的数据库管理系统1.4 SQL2. Mysql的安装2.1 MySQL数据模型3. SQL概述3.1 SQL简介3.2 通用语法3.3 SQL分类4. DDL:操作数据库4.1 数据库的显示讲解4.2 查询4.3 创建数据库4.4 删除数据库4.5 使用数据库4.6 小结5…

linux Qt编译自己的动态库(.so),详细全流程

本篇记录Qt编译动态库全流程 1. 建立工程 首先&#xff0c;打开Qt&#xff0c;新建C Library 工程 点击choose之后&#xff0c;输入项目名称为Example&#xff0c;一直下一步即可 生成的项目里边有三个文件&#xff0c;分别是example.h, Example_global.h, example.cpp exam…

数据结构之:递归思想

&#xff08;一&#xff09;递归概念 将复杂问题 递推分解为最简问题 然后将结果回归的过程 Windows - Linux Linux Linux is not Unix 使用方法&#xff1a; 自己调用自己&#xff08;二&#xff09;斐波那契数列 兔子问题 有一对大兔子 每个月繁衍 一对小兔子&#xff08;一…

【Java 设计模式】UML 之类图

UML 之类图前言&#xff1a;什么是 UML &#xff1f;1 类图概念2 类的表示方式3 类与类之间关系的表示方式3.1 关联关系3.1.1 单向关联3.1.2 双向关联3.1.3 自关联3.2 聚合关系3.3 组合关系3.4 依赖关系3.5 继承关系3.6 实现关系前言&#xff1a;什么是 UML &#xff1f; 定义…

Linux 软件包下载加速工具:APT Proxy

本篇文章将继续介绍这个仅有 2MB 身材大小的 Linux 软件包缓存和加速工具&#xff1a;APT Proxy。 相比老牌的 apt cacher ng 而言&#xff0c;除了尺寸更小、内存占用更低&#xff08;10M以内&#xff09;、它还拥有无需配置&#xff0c;开箱即用等特点。 写在前面 年中的时…

!与~有什么区别

目录 将整型数据转换为二进制的函数 利用函数查看&#xff01;与~之后的数据有何不同 以一个非0数据作为例子 以0作为例子 我们都知道&#xff01;与~都是用于取反的。那么这两个有什么区别呢&#xff1f; 我们百度结果如下&#xff0c;很明显&#xff0c;八股文。我接下…

element-ui时间选择器(DatePicker )数据回显

系列文章目录 第一篇【element-ui】table表格底部合计自定义配置 目录 前言 一、element-ui时间选择器&#xff08;DatePicker &#xff09;是什么&#xff1f; DatePicker 日期选择器 二、返回数据格式 1.引入 总结 前言 需求&#xff1a;element-ui时间选择器&#…

【报错】QT Release NO CMAKE_CXX_COMPILER could be found

NO CMAKE_CXX_COMPILER could be found 错误&#xff1a; Tell CMake where to find the compiler by setting either the environmentvariable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path tothe compiler, or to the compiler name if it …

PostgreSQL数据库动态共享内存管理器——dynamic shared memory segment

首先看dynamic_shared_memory_type GUC参数&#xff0c;该参数用于指定dynamic shared memory implementation类型&#xff08;DSM_IMPL_POSIX、DSM_IMPL_SYSV、DSM_IMPL_WINDOWS、DSM_IMPL_MMAP&#xff0c;定义在src/include/storage/dsm_impl.h文件中&#xff09;。了解一下…

前段入门-CSS

目录1 CSS 快速入门1.1 CSS 的介绍1.2 CSS 的组成2 基本语法2.1 CSS 的引入方式2.1.1 内联样式2.1.2 内部样式2.1.3 外部样式2.2 注释2.3 选择器2.3.1 基本选择器2.3.2 属性选择器2.3.3 伪类选择器2.3.4 组合选择器2.4 总结3 CSS 案例-头条页面3.1 案例效果3.2 案例分析3.2.1 边…

【第三部分 | 移动端开发】4:Rem布局

目录 | Rem布局简介 | 单位 rem | 媒体查询 | 根据不同的媒体引入不同的CSS | less基础 概述与安装 基础使用&#xff1a;创建less文件 基础使用&#xff1a;变量 基础使用&#xff1a;用Esay LESS插件把less文件编译为css 基础使用&#xff1a;嵌套 基础使用&#x…

cuda在windows10安装教程

CUDA安装教程&#xff0c;以Windows10系统为例&#xff1a; CUDA.exe安装 查看电脑的支持的CUDA版本&#xff0c;按照如下教程&#xff1a; 首先找到这个图标&#xff0c;也就是nvidia控制面板&#xff0c;然后打开&#xff1a; 然后点击左下角系统信息 再点击“组件”&…

LabVIEW性能和内存管理 8

LabVIEW性能和内存管理 8 本文介绍LabVIEW性能和内存管理的几个建议8。 MemoryFragmentation内存碎片 内存管理器分配和释放内存需要时间&#xff0c;这会降低执行速度。在某些情况下&#xff0c;即使假设有足够的可用内存&#xff0c;也会发生内存不足错误。 上图显示了实际…

【练拳不练功,到老一场空】深入浅出计算机组成原理

深入浅出计算机组成原理 文章目录深入浅出计算机组成原理计算机的基本组成硬件设备组成CPU内存主板I/O 设备硬盘显卡冯.诺依曼体系结构运算器/处理器单元控制器存储器输入设备输出设备举个栗子&#xff1a;计算机的性能与功耗响应时间吞吐率CPU时钟/主频计算机的功耗计算机的指…

jdk8新特性(Lambda、Steam、函数式接口)

JDK8新特性 JDK8新特性Lambda表达式函数式&#xff08;Functional&#xff09;接口方法引用与构造器引用方法引用构造器引用强大的 StreamAPI创建Stream方式Stream 的中间操作Stream 的终止操作Optional 类Java 8 (又称为jdk 1.8)是Java语言开发的一一个主要版本。 Java 8是ora…

Electron 之通讯模块ipcMain 和 ipcRenderer

Electron一个使用HTML、CSS和JavaScript开发桌面应用程序的框架。Electron可以生成在Windows、macOS和Linux上运行的应用程序&#xff0c;借助Electron可以把我们的web端应用直接移植到桌面端而无需再次开发&#xff0c;这样我们可以使用同一套代码在不同平台上运行应用&#x…

数据收集面可视化

数据收集面可视化&#xff08;Data Collector Surface Visualization&#xff09;分析选项允许用户指定模型中的某一表面&#xff0c;在光线追迹的过程中收集光线数据&#xff0c;并显示或者输出该面的照度&#xff08;或相关的物理量&#xff09;。该分析选项允许计算&#xf…