Java中的LinkedList

news2024/11/27 13:52:29

文章目录

  • 前言
  • 一、LinkedList的使用
    • 1.1 什么是LinkedList
    • 1.2 LinkedList的使用
      • 1.2.1 LinkedList的构造
      • 1.2.2 LinkedList的其他常用方法介绍
      • 1.2.3 LinkedList的遍历
  • 二、LinkedList的模拟实现
  • 三、ArrayList和LinkedList的区别
  • 总结


前言

上一节中我们讲解了Java中的链表,以及几个链表常见的面试题,浅提了一下LinkedList。接下来我们就来详细讲解Java中的LinkedList。


一、LinkedList的使用

1.1 什么是LinkedList

LinkedList官方文档
LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,而是存储在单独的节点中,然后通过引用将节点连接起来了,因此在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。

在这里插入图片描述

在集合框架中,LinkedList也实现了List接口。

注意:

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

1.2 LinkedList的使用

1.2.1 LinkedList的构造

1.无参构造		LinkedList()
2.使用其他集合容器中的元素构造List		public LinkedList(Collection<? extends E> c)

代码如下:

public static void main(String[] args) {
	// 构造一个空的LinkedList
	List<Integer> list1 = new LinkedList<>();
	List<String> list2 = new java.util.ArrayList<>();
	list2.add("JavaSE");
	list2.add("JavaWeb");
	list2.add("JavaEE");
	// 使用ArrayList构造LinkedList
	List<String> list3 = new LinkedList<>(list2);
}

1.2.2 LinkedList的其他常用方法介绍

boolean add(E e)	//尾插e

void add(int index,E element)	//将e插入到index位置

boolean addAll(Collection<? extends E> c)	//尾插c中的元素

E remove(int index)	//删除Index位置的元素

boolean remove(Object o)	//删除遇到的第一个o

E get(int index)	//获取下标index位置的元素

E set(int index,E element)	//将下标为index位置的元素设置为element

void clear()	//清空

boolean contains(Object o)	//判断o是否在线性表中

int indexOf(Object o)	//返回第一个o所在下标

int lastIndexOf(Object o)	//返回最后一个o所在下标

List<E>subList(int fromIndex,int toIndex)	//截取部分list

代码如下:

public static void main(String[] args) {
	LinkedList<Integer> list = new LinkedList<>();
	list.add(1); // add(elem): 表示尾插
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(5);
	list.add(6);
	list.add(7);
	System.out.println(list.size());
	System.out.println(list);
	// 在起始位置插入0
	list.add(0, 0); // add(index, elem): 在index位置插入元素elem
	System.out.println(list);
	list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
	list.removeFirst(); // removeFirst(): 删除第一个元素
	list.removeLast(); // removeLast(): 删除最后元素
	list.remove(1); // remove(index): 删除index位置的元素
	System.out.println(list);
	// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
	if(!list.contains(1)){
		list.add(0, 1);
	}
	list.add(1);
	System.out.println(list);
	System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置
	System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置
	int elem = list.get(0); // get(index): 获取指定位置元素
	list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
	System.out.println(list);
	// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
	List<Integer> copy = list.subList(0, 3); 
	System.out.println(list);
	System.out.println(copy);
	list.clear(); // 将list中元素清空
	System.out.println(list.size());
}

1.2.3 LinkedList的遍历

public static void main(String[] args) {
	LinkedList<Integer> list = new LinkedList<>();
	list.add(1); // add(elem): 表示尾插
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(5);
	list.add(6);
	list.add(7);
	System.out.println(list.size());
	// foreach遍历
	for (int e:list) {
		System.out.print(e + " ");
	}
	System.out.println();
	// 使用迭代器遍历---正向遍历
	ListIterator<Integer> it = list.listIterator();
	while(it.hasNext()){
		System.out.print(it.next()+ " ");
	}
	System.out.println();
	// 使用反向迭代器---反向遍历
	ListIterator<Integer> rit = list.listIterator(list.size());
	while (rit.hasPrevious()){
		System.out.print(rit.previous() +" ");
	}
	System.out.println();
}

二、LinkedList的模拟实现

代码如下:

public class MyLinkedList {
    static class LinkedList {
        public int val;
        public LinkedList prev;
        public LinkedList next;
        public LinkedList(int val) {
            this.val = val;
        }

    }
        public LinkedList head;
        public LinkedList last;
    // 2、无头双向链表实现
        //头插法
        public void addFirst(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head = node;
                last = node;
            } else {
                head.prev = node;
                node.next = head;
                head = node;
            }
        }
        //尾插法
        public void addLast(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head=node;
                last=node;
            } else {
                last.next=node;
                node.prev=last;
                last = node;
            }

        }
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            if(index<0 || index>size()) {
                System.out.println("位置不合法");
            }
            if(index==0) {
                addLast(data);
                return;
            }
            if(index==size()) {
                addLast(data);
                return;
            }

            LinkedList node = new LinkedList(data);
            LinkedList cur = findIndex(index);
            node.next = cur;
            cur.prev.next = node;
            node.prev = cur.prev;
            cur.prev=node;
        }

        public LinkedList findIndex(int index) {
            LinkedList cur = head;
            while (index!=0) {
                cur = cur.next;
                index--;
            }
            return cur;
        }
        //查找是否包含关键字key是否在链表当中
        public boolean contains(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    return true;
                }
                cur = cur.next;
            }
            return false;
        }
        //删除第一次出现关键字为key的节点
        public void remove(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    //头节点
                    if(cur==head) {
                        head = head.next;
                        if (head!=null) {
                            head.prev = null;
                        }
                    } else {
                        //中间 节点和 尾部节点
                        cur.prev.next = cur.next;
                        if(cur.next!=null) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                    return;
                }
                cur=cur.next;
            }
        }
        //删除所有值为key的节点
        public void removeAllKey(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    //头节点
                    if(cur==head) {
                        head = head.next;
                        if (head!=null) {
                            head.prev = null;
                        }
                    } else {
                        //中间 节点和 尾部节点
                        cur.prev.next = cur.next;
                        if(cur.next!=null) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                }
                cur=cur.next;
            }
        }
        //得到的长度
        public int size(){
            int len = 0;
            LinkedList cur = head;
            while (cur!=null) {
                len++;
                cur=cur.next;
            }
            return len;
        }
        public void display(){
            LinkedList cur = head;
            while (cur!=null) {
                System.out.print(cur.val+" ");
                cur=cur.next;
            }
            System.out.println();
        }
        public void clear(){
            LinkedList cur = head;
            while (cur!=null) {
                LinkedList curNext = cur.next;
                cur.prev = null;
                cur.next = null;
                cur = curNext;
            }
            head=null;;
            last=null;
        }

}

三、ArrayList和LinkedList的区别

  1. 在存储空间上,ArrayList在物理上一定连续,LinkedList在逻辑上连续,但物理上不一定连续
  2. ArrayList支持随机访问,时间复杂度为O(1),但是LinkedList不支持,时间复杂度为O(N)
  3. ArrayList在头插时需要搬移元素,效率低O(N),LinkedList只需要修改引用的指向,时间复杂度为O(1)
  4. ArrayList在插入时空间不够时需要扩容,但是LinkedList没有容量的概念
  5. ArrayList应用于“元素高效存储和频繁访问”,LinkedList应用于“任意位置插入和删除频繁”

总结

以上就是今天要讲的内容,本文介绍了LinkedList的使用以及其模拟实现,最后我们对比了ArrayList和LinkedList。

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

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

相关文章

vue3.0中echarts实现中图地图的省份切换,并解决多次切换后地图卡死的情况

一、echarts安装及地图的准备 1、安装echarts npm install echarts2、下载china.js等json文件到项目中的文件夹 map的下载地址&#xff1a; 等审核 二、代码说明 <template><div class"center-body"><div class"map" id"map"…

fork函数详解

文章目录fork函数例子详解工作原理GDB 多进程调试fork函数 fork系统调用用于创建一个新进程&#xff0c;称为子进程&#xff0c;它与进程&#xff08;称为系统调用fork的进程&#xff09;同时运行&#xff0c;此进程称为父进程。创建新的子进程后&#xff0c;两个进程将执行fo…

jvm系列(2)--类加载子系统

目录第2章-类加载子系统内存结构概述简图详细图类加载器子系统类加载器ClassLoader角色类加载过程概述加载阶段链接阶段验证(Verify)准备(Prepare)解析(Resolve)初始化阶段类的初始化时机clinit()1&#xff0c;2&#xff0c;3说明4说明5说明6说明类加载器的分类概述虚拟机自带的…

【web安全】——文件上传的绕过方式

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右铭…

价值创造链路及经营计划

“价值创造过程最主要的环节是建立链接&#xff0c;北京万柳书院在网上热议&#xff0c;其背后是人与人的大量链接&#xff0c;近期热议的湖南卫视春晚亦如是&#xff0c;这种链接为价值的设计、沟通、传递创造条件&#xff1b;企业以客户为中心设计产品&#xff0c;往大了说是…

C++ string类的初步了解

目录 一. 为什么学习string类&#xff1f; 1.C语言中的字符串 2.string类 二. string类的常用接口说明 1.构造 2.容量 size和length capacity clear empty reserve resize 3.元素访问 operator[] at front、back 4.迭代器 ​编辑begin、end rbegin、rend …

数据结构初阶:排序

本期博客我们来到了初阶数据结构最后一个知识点&#xff1a;排序 排序&#xff0c;我们从小到大就一直在接触&#xff0c;按身高、成绩、学号等等不同的排序我们已经历许多&#xff0c;那么各位是按怎样的方法进行排序的呢&#xff1f; 废话不多说这期博客我们对各种排序方法…

测试开发 | 测试平台开发-前端开发之数据展示与分析

本文节选自霍格沃兹测试学院内部教材测试平台的数据展示与分析&#xff0c;我们主要使用开源工具ECharts来进行数据的展示与分析。ECharts简介与安装ECharts是一款基于JavaScript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化…

Unity 使用OpenXR和XR Interaction Toolkit 开发 HTCVive(Vive Cosmos)

Unity 使用OpenXR和XR Interaction Toolkit 开发 HTCVive&#xff08;Vive Cosmos&#xff09; 提示&#xff1a;作者是 Unity 2020.3 以上版本做的开发。开发VR程序需要安装 Steam&#xff0c;SteamVR, (Vive Cosmos,需要再安装VIVEPORT,VIVEConsole) OpenXR 控制设备 &#x…

OpenCV(12)-OpenCV的机器学习

OpenCV的机器学习 基本概念 计算机视觉是机器学习的一种应用&#xff0c;而且是最有价的应用 人脸识别 哈尔(Haar)级联方法深度学习方法(DNN) Haar人脸识别方法 哈尔(Haar)级联方法是专门为解决人脸识别而推出的&#xff0c;在深度学习还不流行时&#xff0c;哈尔已可以商…

Android 深入系统完全讲解(21)

关键性 EGLSurface 代码位置 继续再看看&#xff0c;代码跑到 C 里面去了。 然后关键点&#xff1a; 获取本地窗口&#xff0c;创建 Surface&#xff0c;然后 toEGLHandle 进行包裹&#xff0c;变成 EGL 上下文。 EGLSurface 。 绘制的设计本质逻辑 在这里就回归一点&#xff…

Unity学习笔记--File.ReadAllLines和File.ReadAllText的使用以及注意事项(一定要看到最后!!!)

目录前言一、File.ReadAllLines参数返回例子二、File.ReadAllText参数返回例子注意事项可能出现的问题总结前言 最近在做文件存储以及读取的时候&#xff0c;需要用到C#给我们提供的类&#xff1a;File 具体使用方法可以看官方文档&#xff1a;C# File 类 这篇文章只会说File.…

深度学习基础理念(一)

文章目录1. 机器学习 Machine Learing机器学习类别2. 机器如何找函数深度学习输入类型和输出类型机器如何找函数的1. 机器学习 Machine Learing 什么是机器学习&#xff0c;顾名思义 机器 拥有会学习的能力&#xff0c;机器学习就是让机器具备能够找函数的能力 机器学习就是找…

【C语言课程设计】通讯录(1.0版本)

前言 相信各位对于通讯录都不是很陌生吧。通讯录我们在学校的大作业&#xff0c;课程设计经常会去使用它。那么今天我们将使用C语言来实现一个简单的通讯录。 目录 前言 一、通讯录的需求 二、工程文件的创建 三、通讯录的声明和定义 四、通讯录各函数的声明和定义 五、通…

Mysql入门技能树-数据查询-练习篇

SELECT 下列 SQL 语句&#xff0c;哪一项不合法&#xff1f; 答案是&#xff1a;C select now(),3.14 now() |3.14| ----------------------- 2023-01-16 16:47:04|3.14|MySQL查询表中所有的数据可以通过“SELECT * 通配符”或者“SELECT 所有字段”实现。 SE…

hadoop3.x源码编译及cmake的问题解决:CMake failed with error code 1

一、准备工作 基础环境&#xff1a;centos7 &#xff08;1&#xff09;官方源码中编译之前对基础环境及版本的要求&#xff08;重点是红色部分&#xff09; Requirements: * Unix System* JDK 1.8 * Maven 3.3 or later * ProtocolBuffer 2.5.0 * CMake 3.1 or newer (if com…

OSCP-Vulnhub靶机记录-Hacker_Kid-v1.0.1

Vulnhub靶机记录-Hacker_Kid-v1.0.1介绍&安装信息收集页面源代码DIG信息收集xxe漏洞探测9999端口SSTI模板注入发现具有Capabilities特殊操作权限的程序原理介绍&安装 靶机名称&#xff1a;Hacker_Kid-v1.0.1 靶机难度&#xff1a;中等 虚拟机环境&#xff1a;此靶机推…

【Linux】线程互斥

目录&#x1f308;前言&#x1f338;1、Linux线程互斥&#x1f367;1.1、线程间互斥相关背景概念&#x1f368;1.2、互斥量(锁)相关背景&#x1f36f;1.3、互斥量(锁)相关API&#x1f36f;1.3.1、初始化和销毁互斥锁&#x1f370;1.3.2、互斥量加锁和解锁&#x1f372;1.3.3、互…

Python爬虫403错误的解决方案

前言程序使用一段时间后会遇到HTTP Error 403: Forbidden错误。 因为在短时间内直接使用Get获取大量数据&#xff0c;会被服务器认为在对它进行攻击&#xff0c;所以拒绝我们的请求&#xff0c;自动把电脑IP封了。 解决这个问题有两种方法。一是将请求加以包装&#xff0c;变成…

1.浮动float

提示&#xff1a;如果多一个盒子&#xff08;都设置浮动&#xff0c;则它们会按照属性值一行内显示并且顶端对齐排列&#xff09; 注意&#xff1a; 浮动的元素是互相贴靠在一起的&#xff0c;&#xff08;没有缝隙&#xff09;&#xff0c;如果父级宽度装下这些浮动盒子&#…