当前位置: 首页 > news >正文

Java学习20

上午 3h LinkedList 深度学习

1.1 LinkedList 底层结构与核心特点(0.6h)

底层核心

  • ArrayList底层:动态可变数组
  • LinkedList底层:双向双向链表
  • 链表没有固定连续内存空间,不存在数组扩容、元素移位问题

核心特性

  1. 元素以节点形式存储,每个节点:存数据 + 上一个节点地址 + 下一个节点地址
  2. 无初始容量、无扩容机制,元素按需创建节点
  3. 首尾增删极快,只需要修改节点引用地址
  4. 根据索引查询、中间位置操作很慢,必须从头 / 尾逐个遍历查找

结构对比表(必背)

表格

集合底层结构查询 / 遍历中间增删首尾增删
ArrayList动态数组极快
LinkedList双向链表极快

核心结论

  • 查多改少、展示列表、遍历数据 → 优先ArrayList
  • 频繁头尾增删、做队列 / 栈结构 → 优先LinkedList

1.2 LinkedList 独有首尾专属方法(1.2h)

继承 List 全部通用方法,额外提供首尾操作专属 API,适合链表结构。

表格

专属方法作用
addFirst(E e)集合头部添加元素
addLast(E e)集合尾部添加元素
getFirst()获取第一个元素
getLast()获取最后一个元素
removeFirst()删除并返回首元素
removeLast()删除并返回尾元素

完整案例代码 + 逐行解析

java

运行

import java.util.LinkedList; public class LinkedListFirstLastDemo { public static void main(String[] args) { // 1. 创建LinkedList集合,泛型约束存储字符串 LinkedList<String> link = new LinkedList<>(); // 2. 尾部添加(等价普通add) link.addLast("张三"); link.addLast("李四"); // 3. 头部添加 link.addFirst("赵六"); System.out.println("首尾添加后:" + link); // 4. 获取首尾元素 String first = link.getFirst(); String last = link.getLast(); System.out.println("首元素:" + first); System.out.println("尾元素:" + last); // 5. 删除首尾元素 link.removeFirst(); link.removeLast(); System.out.println("删除首尾后:" + link); } }
逐行解释
  1. LinkedList<String> link = new LinkedList<>();创建双向链表集合,仅允许存储字符串;
  2. addFirst / addLast:利用链表引用特性,直接绑定头尾节点,效率极高;
  3. getFirst/getLast:直接获取头尾节点,无需遍历;
  4. removeFirst/removeLast:断开头尾节点引用,自动回收节点,无元素移位。

1.3 LinkedList 通用 List 方法(0.6h)

核心说明

LinkedList实现了List接口:

  • 满足 List 三大特性:有序、可重复、带索引
  • 完全复用:add()、remove(索引)、set()、get()、size()、clear()
  • 支持 Day14 全部三种遍历:普通 for、增强 for、迭代器

通用索引操作代码示例

java

运行

import java.util.LinkedList; public class LinkedListCommonDemo { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<>(); list.add(10); list.add(20); list.add(30); // 根据索引获取 System.out.println("索引1元素:" + list.get(1)); // 根据索引修改 list.set(0, 99); // 根据索引删除 list.remove(2); System.out.println("最终集合:" + list); } }
关键短板

LinkedList调用get(索引)时,底层会从头节点循环遍历找位置,数据量大时性能很差


1.4 适用场景总结(0.6h)

  1. 适合场景
  • 频繁在头部、尾部插入 / 删除数据
  • 实现简单队列、栈、消息排队结构
  • 数据量波动大,不想考虑数组扩容
  1. 不适合场景
  • 大量根据索引查询、分页展示、列表遍历
  • 项目常规业务数据存储(90% 场景用 ArrayList)

下午 2.5h 泛型 + 迭代器完整用法 + 增强 for 底层

2.1 泛型 核心概念与作用(1h)

1)为什么需要泛型

  • 不写泛型:集合默认存储Object类型,什么类型都能存
  • 取出元素必须强制类型转换,代码繁琐
  • 极易发生类型转换异常 ClassCastException

2)泛型核心三大作用

  1. 类型约束:规定集合只能存指定类型
  2. 编译校验:编译阶段就报错,杜绝存错数据
  3. 省去强转:取出元素直接是目标类型,简化代码

3)基础语法

java

运行

集合<存储类型> 变量名 = new 实现类<>();

4)无泛型 / 有泛型 对比完整代码

① 无泛型(弊端演示)

java

运行

import java.util.ArrayList; public class NoGenericDemo { public static void main(String[] args) { // 无泛型,默认Object ArrayList list = new ArrayList(); list.add("Java"); list.add(123); // 乱存,编译不报错 // 取出必须强转 String s = (String) list.get(0); // String s2 = (String) list.get(1); // 运行报错:类型转换异常 } }
② 有泛型(安全规范写法)

java

运行

import java.util.ArrayList; public class GenericDemo { public static void main(String[] args) { // 泛型约束:只能存String ArrayList<String> list = new ArrayList<>(); list.add("Python"); // list.add(666); 编译直接报错,防止错误数据存入 // 无需强转,直接取值 String str = list.get(0); System.out.println(str); } }

5)泛型书写规则

  • 接口 / 类后加尖括号:List<E>、ArrayList<E>、LinkedList<E>
  • 泛型只能写引用类型:String、Integer、自定义实体类
  • 基本类型不能写:int不行,要用包装类Integer

2.2 迭代器 Iterator 完整用法(0.8h)

1)迭代器定位

  • 所有Collection单列集合通用遍历方式
  • 不依赖索引,适配数组、链表所有集合
  • 遍历集合时,安全删除元素唯一方案

2)三大核心方法

  1. iterator():调用集合方法,获取迭代器对象
  2. hasNext():判断是否存在下一个未遍历元素,返回布尔值
  3. next():获取下一个元素,指针后移

3)标准默写模板 + 完整代码

java

运行

import java.util.ArrayList; import java.util.Iterator; public class IteratorFullDemo { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("高数"); list.add("英语"); list.add("Java"); // 1. 获取迭代器对象 Iterator<String> it = list.iterator(); // 2. 循环判断是否有下一个元素 while (it.hasNext()){ // 3. 取出元素 String course = it.next(); System.out.println(course); } } }
逐行解析
  1. list.iterator():集合底层生成迭代器,记录遍历起始位置;
  2. it.hasNext():内部判断指针是否到达集合末尾;
  3. it.next():取出当前元素,同时迭代器指针向后移动一位。

2.3 增强 for 循环底层原理(0.7h)

1)底层本质

增强 for 循环底层完全就是迭代器是迭代器的简化写法,简化代码、去掉迭代器对象书写

2)标准格式

java

运行

for(元素类型 变量名 : 集合/数组){ 循环操作 }

3)代码演示

java

运行

for (String s : list) { System.out.println(s); }

4)致命限制(高频考点)

遍历过程中不能添加、删除集合元素会抛出:ConcurrentModificationException 并发修改异常

  • 原因:增强 for 底层迭代器不允许遍历期间修改集合长度
  • 解决方案:需要增删,必须用原生迭代器

晚上 1.5h 综合练习 + List 全复盘

3.1 今日必做实战练习(可直接抄写运行)

练习 1:LinkedList 全套首尾操作

java

运行

import java.util.LinkedList; public class LinkPractice { public static void main(String[] args) { LinkedList<String> link = new LinkedList<>(); link.addFirst("元素1"); link.addLast("元素2"); link.addFirst("元素0"); System.out.println("首元素:" + link.getFirst()); System.out.println("尾元素:" + link.getLast()); link.removeFirst(); link.removeLast(); System.out.println(link); } }

练习 2:三种方式遍历 LinkedList

java

运行

import java.util.Iterator; import java.util.LinkedList; public class LinkTraverse { public static void main(String[] args) { LinkedList<Integer> numList = new LinkedList<>(); numList.add(1); numList.add(2); numList.add(3); // 1.普通for for (int i = 0; i < numList.size(); i++) { System.out.print(numList.get(i)+" "); } System.out.println("\n--------"); // 2.增强for for (Integer n : numList) { System.out.print(n+" "); } System.out.println("\n--------"); // 3.迭代器 Iterator<Integer> it = numList.iterator(); while (it.hasNext()){ System.out.print(it.next()+" "); } } }

练习 3:泛型安全对比

自行对比无泛型随意存、有泛型限制类型的编译区别,加深理解。


3.2 高频面试简答(直接背诵)

  1. ArrayList 和 LinkedList 区别?
  • ArrayList:底层数组,查询遍历快,中间增删慢;
  • LinkedList:底层双向链表,首尾增删快,索引查询慢。
  1. 泛型的作用?约束集合存储类型,编译期校验,避免类型转换异常,省略强制转换。

  2. 增强 for 和迭代器关系?增强 for 底层基于迭代器,是简化写法;本质完全一致。

  3. 增强 for 为什么不能遍历删元素?底层迭代器检测到集合长度被修改,触发并发修改异常。


3.3 Day20 核心知识点汇总

  1. LinkedList:双向链表结构,独有首尾 API,适合头尾高频操作
  2. 泛型:统一类型、代码安全、简化转型操作
  3. 迭代器:集合通用遍历,支持遍历中删除元素
  4. 增强 for:语法简化,底层迭代器,禁止遍历增删

Day20 验收标准(对照自查)

✅ 能口述 ArrayList / LinkedList 底层、优劣、使用场景✅ 熟练手写 LinkedList 首尾增删代码✅ 掌握泛型定义格式、作用、基本使用✅ 独立默写迭代器标准遍历代码✅ 理解增强 for 底层原理 + 并发修改异常原因

关于ArrayList和LinkedList的区分

一、先记两个终极比喻(一辈子不忘)

ArrayList = 电影院一排连坐的座位(动态数组)

  • 座位是连在一起
  • 想找第 5 个人,直接跳过去,超快
  • 中间加人、减人,后面所有人都要挪位置,超慢

LinkedList = 幼儿园小朋友手拉手(双向链表)

  • 每个人只拉着前面和后面的人
  • 不占连续空间,随便加人
  • 想找第 5 个人,必须从第一个开始数,很慢
  • 首尾加人、减人,超级快,只需要松手拉手

二、最核心区别(4 句话背会)

  1. ArrayList 底层是:动态数组
  2. LinkedList 底层是:双向链表
  3. ArrayList:查询快、增删慢
  4. LinkedList:首尾增删快、查询慢

三、详细对比(一看就懂)

1. 结构区别

ArrayList(动态数组)

  • 内存连续、挨着
  • 有索引,直接跳转到任意位置
  • 满了会自动扩容 1.5 倍

LinkedList(双向链表)

  • 内存不连续、分散
  • 每个元素存:前一个人 + 自己 + 后一个人
  • 没有扩容,来一个加一个

2. 速度区别(最重要)

表格

操作ArrayList(数组)LinkedList(链表)原因
随机查询(get)🟢极快🔴数组直接跳;链表要从头数
中间增删🔴🟡一般数组要挪位置;链表只需改拉手
首尾增删🟡🟢极快链表只需要松手、拉手

3. 方法区别

ArrayList 通用方法

  • add、get、remove、set(依靠索引)

LinkedList多了首尾专用方法

  • addFirst()头加
  • addLast()尾加
  • getFirst()拿头
  • getLast()拿尾
  • removeFirst()删头
  • removeLast()删尾

这些方法ArrayList 没有!


四、开发中到底用谁?(90% 情况都用这个)

开发首选:ArrayList

因为业务中90% 都是查询、展示列表

什么时候用 LinkedList?

  • 队列(排队)
  • (先进后出)
  • 频繁头插、尾插

五、终极总结(3 句背会)

  1. ArrayList = 连续数组 → 查询快、中间增删慢
  2. LinkedList = 双向链表 → 首尾增删快、查询慢
  3. 日常开发永远用 ArrayList,特殊场景才用 LinkedList
http://www.jsqmd.com/news/733059/

相关文章:

  • BMR技术:单驱动全频扬声器的创新解决方案
  • RimWorld终极角色定制指南:EdB Prepare Carefully完全解析
  • 免费不花钱,就能搭建企业级备份方案,你还在等什么?
  • 不同操作系统下的tftp指令
  • 微信防撤回补丁终极指南:如何永久保留被撤回的消息
  • NRF24L01模块选型与实战:对比“增强型ShockBurst”与“直接模式”到底该怎么选?
  • MCP-SuperAssistant:AI插件开发调试与运维一体化工具链实践
  • 开源恶意域名情报库 2026-4-30
  • Windows 11安卓子系统(WSA)终极指南:在电脑上免费运行Android应用的完整教程
  • WzComparerR2终极指南:如何轻松解密和可视化冒险岛游戏数据
  • 多模型聚合平台如何帮助开发者优化大模型API使用成本与效果
  • 拯救失效二维码的奇妙之旅:QRazyBox让损坏的二维码重获新生
  • Cursor智能体开发:云端代理Cloud Agents概述
  • ncmdump终极指南:3分钟解锁网易云音乐NCM格式限制
  • 终极GTNH汉化指南:3分钟为格雷科技新视野安装百万字中文翻译
  • 【伽马龙广告公司简介】
  • 为Claude Code配置Taotoken作为后端大模型服务提供方
  • Cursor智能体开发:安全评审
  • 如何实现跨平台游戏串流技术架构设计
  • 企业级开源资产管理系统:构建IT资产全生命周期管理的终极解决方案
  • 在数据爬虫项目中集成 Taotoken 大模型 API 进行智能内容解析
  • python中,asyncio.create_task和await的区别与联系
  • 024、多工具协调:Agent的规划与执行
  • CA证书
  • 避坑指南:在Ubuntu 22.04上为通义千问安装flash-attention,我踩过的那些环境依赖的坑
  • VinXiangQi象棋连线工具:基于YOLOv5的智能对局助手深度解析
  • 当熔断器遇见分支预测:两种“猜错就惩罚”的系统哲学
  • 终极解码方案:如何让老旧电脑流畅播放4K HDR视频?
  • 告别公网IP烦恼:用cpolar在Windows上SSH远程连接家里CentOS服务器(保姆级图文教程)
  • JWT原理与Token