Java集合分类
一. Java 集合:Collection 单列集合与 Map 双列集合1. Collection 单列集合每次存储单个元素只有值没有对应的键。例子脉劫、康帅傅、粤利粤每个元素独立存在。子接口List有序、可重复、有索引。代表ArrayList、LinkedListSet无序、不可重复、无索引。代表HashSet、TreeSet2. Map 双列集合存储键值对key-value一组数据包含键 (key) 和值 (value) 两部分。key键唯一不可重复value值可以重复常用实现类HashMap、LinkedHashMap、TreeMap二. Collection 单列集合一、集合对比总表List 系列有序、可重复、有索引集合底层结构特点适合场景ArrayListObject动态数组有序、可重复、有索引查询快中间增删慢JDK8懒加载首次add容量10扩容1.5倍查询多中间增删少LinkedList双向链表有序、可重复、有索引查询慢首尾增删极快无扩容机制结点内存不连续频繁对首尾增删查询少Set 系列不可重复集合底层结构特点适合场景HashSet哈希表数组链表/红黑树无序、不可重复、无索引依靠hashCode()equals()去重默认容量16加载因子0.75扩容2倍只去重不关心顺序LinkedHashSet哈希表双向链表插入有序、不可重复、无索引哈希表去重链表记录插入顺序需要去重同时保留存入顺序TreeSet红黑树不可重复、自然排序、无索引元素必须实现Comparable接口自动从小到大排序去重二、List集合考点List共同特点有序、可重复、有索引。List独有4个索引方法void add(int index,E element)在指定位置插入元素E remove(int index)删除指定索引元素返回被删元素E set(int index,E element)修改指定索引元素返回旧元素E get(int index)获取指定索引元素ArrayList底层底层Object[] elementDatasize是实际元素个数不等于数组length。JDK8无参构造创建空数组第一次add才初始化容量10扩容为原容量1.5倍底层Arrays.copyOf拷贝数组。数组查询快中间增删慢需要移动大量元素。LinkedList底层底层双向链表结点保存【前驱地址值后继地址】内存不连续,而且占内存。特点查询慢首尾增删极快,增删相对快。特有首尾方法addFirst、addLast、getFirst、getLast、removeFirst、removeLast。没有数组没有扩容。get(index)会就近遍历查询效率低。三、Set集合考点Set共同特点不可重复没有索引不能使用普通for循环(fori)遍历。✅ Set可用遍历方式① 迭代器 Iterator② 增强for循环 for-each底层是迭代器③ Lambda forEachJDK8⚠️ 增强for、Lambda forEach遍历中不能直接用集合的add/remove会并发修改异常边遍历边删除只能用迭代器it.remove()HashSet底层原理底层哈希表数组链表红黑树JDK8,之前是数组链表。默认容量16加载因子0.75(平衡哈希冲突与内存开销)超过阈值扩容为2倍,如:扩容阈值 容量 * 加载因子元素个数超过阈值16*0.7512就按两倍扩容。去重规则先调用hashCode()得到哈希值计算数组下标下标位置有元素时哈希值不同直接挂链表哈希值相同调用equals()对比内容equals返回true判定重复不存储。自定义对象存入HashSet必须重写hashCode()和equals()否则无法去重。链表长度≥8数组≥64链表转红黑树,提升查询速度红黑树节点数量≤6红黑树退化成链表,减少维护红黑树开销。为什么不选平衡二叉树平衡二叉树旋转次数多红黑树牺牲一部分严格平衡减少旋转综合效率更高。LinkedHashSetHashSet子类哈希表做去重双向链表记录插入顺序存入和取出顺序一致。TreeSet底层红黑树不可重复、自动排序、无索引,元素自动排序存入元素需要实现Comparable接口。⚠️ 不是存入顺序是元素本身大小的自然排序。去重规则根据元素的比较结果判断重复不再依赖 hashCode 和 equals。如果两个元素比较返回 0 → 判定为重复不存入集合。注意 :HashSet存入自定义对象成员变量值相同却不能去重原因自定义类默认继承 Object 的 hashCode() 和 equals() 方法Object.hashCode()基于对象地址生成哈希值 ,而当new了一个对象之后,两个对象地址不同 → 默认hashCode不同直接判定为不同对象存入集合不会去重。Object.equals()底层比较对象地址不比较对象里面的属性值HashSet存自定义对象,如果希望Set集合认为2个内容一样的对象是重复的,必须重写对象的hashCode() and equals()方法,按属性判断重复补充hashCode与equals的关系面试必背hashCode相等对象不一定相等存在哈希碰撞hashCode不相等对象一定不相等HashSet去重规则① 先判断hashCodehashCode不同直接判定不同对象② hashCode相同再调用equals比较内容③ equals返回true才判定为重复元素拒绝存入规范重写equals()必须同时重写hashCode()保证属性相同的对象hashCode结果也相同。四、并发修改异常 ConcurrentModificationException触发迭代器遍历集合时直接调用集合的add/remove修改集合,出异常。解决方案① List有索引普通for循环删除后 i - -(因为删除元素之后后一个元素会补位)或者倒序遍历删除② List / Set通用迭代器遍历使用it.remove()删除注意增强for循环、Lambda forEach只适合读取遍历遍历中不能增删会报并发修改异常五、迭代器 IteratorhasNext()判断是否还有下一个元素返回booleannext()取出下一个元素指针后移it.remove()删除刚刚next拿到的元素同步更新modCount不会并发修改异常必须先next才能remove三 .Map双列集合1 . Map概述Map是双列集合一次存储一对键值对keyvaluekey唯一、不可重复key重复会覆盖旧valuevalue可重复2. Map常用实现类HashMap底层哈希表key无序不重复LinkedHashMap哈希表双向链表key存取有序不重复TreeMap红黑树key自动排序不重复3. Map常用方法put(K key,V value)添加键值对key存在则覆盖旧valueget(Object key)根据key获取value找不到返回nullremove(Object key)按key删除返回被删除valuecontainsKey(key)判断是否存在该keycontainsValue(value)判断是否存在该valuekeySet()获取全部key返回Set集合entrySet()获取全部键值对对象Entry4. Map两种遍历keySet遍历获取所有key循环key调用get拿valueSetStringkeysmap.keySet();for(Stringkey:keys){System.out.println(key : map.get(key));}2.entrySet 遍历推荐效率更高Map.Entry 代表单个键值对对象可以 getKey ()、getValue ()SetMap.EntryString,IntegerentrySetmap.entrySet();for(Map.EntryString,Integerentry:entrySet){Stringkentry.getKey();Integerventry.getValue();}Lambda forEachJDK1.8 新增代码最简map.forEach((k,v)-System.out.println(kv));Map底层原理1.HashMap 底层原理重点底层哈希表数组 单向链表 红黑树HashSet 底层就是 HashMapHashSet 存入的元素就是 HashMap 的 keyvalue 是固定占位对象。存入流程key 调用 hashCode 计算哈希值定位数组下标同一下标位置对比 keyhashCode 相同 equals 返回 true → key 重复覆盖旧 valuehashCode 相同 equals 返回 false → 挂链表JDK8 树化规则链表长度≥8数组长度≥64链表转为红黑树提高查询速度红黑树节点≤6退化为单向链表扩容参数默认容量16加载因子 0.75阈值 容量 * 0.75到达阈值数组扩容 2 倍。自定义对象作为 HashMap 的 key必须重写 hashCode () 和 equals ()2. LinkedHashMap底层哈希表 双向链表key 存取有序去重规则同 HashMap。3.TreeMap底层红黑树key 自动排序排序与去重依靠 Comparable/Comparator不依赖 hashCode 和 equals。比较返回 0判定 key 重复覆盖 value。HashMap 面试考点HashMap 允许一个 null 的 keyvalue 允许多个 nullTreeMap 的 key 不能为 null。HashMap线程不安全多线程推荐 ConcurrentHashMap。HashMap vs HashtableHashMapJDK1.2线程不安全key 可以 null默认容量 16扩容 ×2HashtableJDK1.0方法加 synchronized线程安全key 不能 null默认容量 11扩容 ×21四 . Stream 流一.认识 Stream 流Stream 叫做流,是 JDK8 新特性用来对集合、数组进行数据处理的流水线。不是集合,不存储数据只是对数据源的数据做加工,结合了Lambda 表达式。作用简化集合 / 数组的遍历、过滤、排序、去重、统计等操作代码更简洁不用手写大量 for 循环。步骤 : ①获取 Stream 流 → ②中间操作过滤、排序、去重 → ③终结操作得到结果1.获取 Stream 流Stream 流代表一条流水线和数据源建立连接,得到流对象数据源可以是Collection集合、数组// 集合获取流ListStringlistnewArrayList();StreamStringstreamlist.stream();// 数组获取流String[]arr{西湖,乌镇};StreamStringstream2Arrays.stream(arr);✅ 作用只是建立管道还没有真正处理数据2. 中间操作流水线过滤、排序、去重中间操作 :链式调用方法处理数据特点延迟执行不触发计算只是把操作保存起来filter()过滤sorted()排序distinct()去重limit()取前 n 个skip()跳过前 n 个3. 获取结果终结操作触发流水线执行一旦执行流就关闭不能再用collect()收集到新集合List/Setcount()统计元素个数forEach()遍历publicclassStreamDemo{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(西湖);list.add(乌镇);list.add(西湖);list.add(西塘);// Stream三步ListStringresultlist.stream()//1. 获取流建立流水线.distinct()//2.中间操作去重.filter(s-s.length()2)//2.中间操作过滤保留2个字景点.collect(Collectors.toList());//3.终结操作收集成新ListSystem.out.println(result);}}中间操作不会执行只有遇到终结方法整条流水线才运行Stream 流不能复用终结之后流就关闭不能再次调用Stream 不会修改原来的集合数据源处理结果放到新集合对比原来的普通 for 循环 VS Stream 流for 循环自己写遍历、if 判断、创建集合代码长Stream链式调用一行完成过滤、去重、收集代码简洁五 . Collections 工具类方法名称说明public static T booleanaddAll(Collection? super T c, T… elements)给集合批量添加元素public static voidshuffle(List? list)打乱List集合中的元素顺序public static T voidsort(ListT list)对List集合中的元素进行升序排序public static T void sort(ListT list, Comparator? super T c)对List集合中元素按照比较器规则排序1.Collections和Collection区别Collection 是集合顶层接口List、Set 的父接口Collections 是集合工具类提供静态方法操作集合对象。2.shuffle 只能作用于List 集合用来随机打乱元素顺序。3.sort(List list)默认自然升序sort(List list, Comparator)自定义比较规则排序支持 Lambda。六 . subList 集合复制 浅拷贝深拷贝1. List—subList 集合截取核心list.subList(fromIndex, toIndex)区间左闭右开[from, to)包含起始索引不包含结束索引返回值原集合的视图不是全新 ArrayListsubList 没有新建数组底层还是原 List。修改子集合元素set/remove原集合同步变化如果原集合发生结构性修改add/remove再操作 subList抛出 ConcurrentModificationException参数不能负数toIndex 不能大于 list.size ()否则抛IndexOutOfBoundsExceptionsubList(2,2) 返回空集合不报错// 推荐生成全新List和原list互不影响ListStringnewListnewArrayList(list.subList(1,3));ListStringsublist.stream().skip(1)// 跳过前1个.limit(2)// 取2个元素.collect(Collectors.toList());Stream 方式返回新集合无视图陷阱性能略低于 subList。一句话记忆subList 是视图不是新集合想安全就包一层 new ArrayList。集合复制一个集合倒入另一个集合✅方式 1构造方法新建目标集合// 新建target把source全部元素倒入ListUsertargetnewArrayList(source);方式 2addAll目标集合已存在追加元素ListUsertargetnewArrayList();target.addAll(source);错误写法不是拷贝只是引用赋值:ListUsertargetsource;// target和source指向同一个集合增删任意一个两边都会变重点new ArrayList(source) / addAll() 都是浅拷贝只是新建集合容器集合里面存放的对象还是同一个引用。修改对象属性源集合对象同步变化。浅拷贝集合转为深拷贝集合stream map 逐个新建对象:ListUsertargetsource.stream().map(oldUser-{UsernewUsernewUser();newUser.setId(oldUser.getId());newUser.setName(oldUser.getName());returnnewUser;}).collect(Collectors.toList());浅拷贝创建新外层对象基本类型复制值引用类型只复制对象地址新旧对象共用同一个子对象。修改子对象属性原对象跟着变。深拷贝创建全新外层对象并且递归新建所有引用类型子对象。新旧对象完全独立修改任意一方内部对象互不影响。1.subList 返回原集合视图不是新集合原集合结构性修改会抛并发异常想安全拷贝需要new ArrayList(subList)。2.new ArrayList(source) 和 addAll 是浅拷贝新建集合容器但元素对象共用引用。3.list.sort 原地修改原集合stream.sorted 返回新集合原集合不变。4.Comparable 是类自带比较规则Comparator 是临时比较器推荐 Lambda 写法。5.浅拷贝新建外层对象引用成员共享深拷贝所有层级对象全部新建完全隔离。6.集合浅拷贝陷阱集合增删互不影响但是修改集合里面对象属性源集合对象同步变化。问User u2 u1 是浅拷贝吗不是。只是引用赋值没有创建新对象两个引用指向同一个对象。浅拷贝一定会创建新外层对象。问浅拷贝集合中 target.setAddress(new Address()) 修改引用原对象会变吗不会。只是把拷贝对象的引用指向新对象。只有修改同一个子对象内部属性时才会互相影响。

相关新闻

ROS2 实战 | 手写 TF2 海龟实时坐标广播器(含完整避坑指南)

ROS2 实战 | 手写 TF2 海龟实时坐标广播器(含完整避坑指南)

ROS2 实战 | 手写 TF2 海龟实时坐标广播器(含完整避坑指南) 摘要:本文从零实现一个 ROS2 Python 节点,实时订阅 turtlesim 海龟位姿并广播 TF 坐标变换。重点修正了官方教程中常见的 Odometry/Pose 混用、__name__ 入口错误、--symlink-install 开发技巧等高频踩坑点,附完…

2026/9/24 17:41:39 阅读更多 →
SqueezeNet:Fire模块驱动,极致参数压缩的初代轻量化CNN标杆

SqueezeNet:Fire模块驱动,极致参数压缩的初代轻量化CNN标杆

一、时代痛点:早期CNN的体积与部署困境 2016年之前的经典CNN模型,普遍存在模型臃肿、参数量爆炸、部署门槛极高的问题,严重限制了深度学习的落地应用,也是SqueezeNet诞生的核心动因。 第一,33卷积参数冗余严重。AlexNe…

2026/9/24 17:41:39 阅读更多 →
deepagents之任务规划与分解

deepagents之任务规划与分解

前言 agent或llm第一个蜕变,是它可以执行工具了。 但是agent开始变的强大,其实是从LLM能力提升,agent可以根据任务,自主规划任务与执行开始的。 今天我们就看下deepagents如何进行任务的规划与分解。 为什么agent需要规划能力 简单…

2026/9/24 17:41:39 阅读更多 →

最新新闻

Linux与Windows系统运维:参数查询与配置命令对照实战

Linux与Windows系统运维:参数查询与配置命令对照实战

很多时候,我们干的活儿并不是什么高深莫测的架构设计,反而是那些每天都在重复的“查一下参数、改一个配置”。尤其是当你的手头同时管着 Windows 服务器和 Linux 服务器时,这种“精神分裂”的感觉会特别明显:明明在 Windows 上用图…

2026/9/24 18:28:13 阅读更多 →
RabbitMQ安装详解:Windows与Docker高频坑与权限排查

RabbitMQ安装详解:Windows与Docker高频坑与权限排查

先聊点实际的。你点进这篇文章,多半是因为项目里突然要用消息队列,或者面试题刷到“RabbitMQ和Kafka怎么选”,又或者已经在Windows上装了RabbitMQ,结果服务死活起不来,管理界面也打不开。不管你是哪种情况,…

2026/9/24 18:28:13 阅读更多 →
Linux与Windows参数查询与配置:双系统实战速查手册

Linux与Windows参数查询与配置:双系统实战速查手册

1. 项目背景:为什么我要维护一份“Linux与Windows参数查询与配置”手册自从开始同时接触Linux服务器和Windows桌面环境,我就一直被同一个问题反复折磨:某个参数上次明明调通了,下次换台机器又得从头翻文档。更让人崩溃的是&#x…

2026/9/24 18:28:13 阅读更多 →
Flutter状态边界:UI树才是决定setState刷新范围的关键

Flutter状态边界:UI树才是决定setState刷新范围的关键

有人问我一个很经典的问题:setState明明调了,数据也变了,界面就是不动,到底哪里出了问题?我听完他的代码描述,第一反应不是去看状态管理库配没配好,而是反问他一句:你这段状态&#…

2026/9/24 18:28:13 阅读更多 →
基于OpenCV模板匹配的车牌识别毕业设计实战指南

基于OpenCV模板匹配的车牌识别毕业设计实战指南

简介:这是一套基于OpenCV模板匹配的车牌识别毕业设计源码,使用Python 3.8与OpenCV 4.2开发,并配有简单的GUI界面。项目面向计算机相关专业的学生或课程设计用户,主要解决从车辆图像中定位车牌、校正倾斜、判别牌照颜色、分割字符并…

2026/9/24 18:28:13 阅读更多 →
【Coze】【视频】治愈系老爷爷工作流

【Coze】【视频】治愈系老爷爷工作流

今天给大家演示一个 老爷爷语录视频自动生成工作流。该工作流通过大语言模型和图像生成模型的协作,自动完成从文本语录生成、格式化处理、配图生成,再到视频合成和音频配乐的完整流程。结合效果展示,用户只需提供简单的输入,就能得到带有温馨画面和背景音乐的成品视频,大幅…

2026/9/24 18:27:12 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →