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

2025/7/14——java学习总结

集合进阶学习总结:从单列到双列,贯通接口与源码的全维度突破

一、核心知识深耕:集合体系与底层逻辑拆解

(一)Collection 接口:单列集合的行为规范

作为 ListSet 的顶层接口,定义 增删查遍历 的通用契约:

  • 核心方法:add(E)remove(Object)iterator()size()contains(Object)
  • 设计哲学:通过接口解耦 “行为定义” 与 “实现细节”(如 ArrayList 用数组、LinkedList 用链表),支持面向抽象编程。

(二)迭代器(Iterator):遍历的统一范式

  • 核心能力hasNext() 判空、next() 取值、remove() 删除(需紧跟 next() 调用);
  • 底层机制
    • 快速失败(fail-fast):通过 modCount(集合修改次数)与 expectedModCount(迭代器记录的修改次数)对比,检测并发修改,抛出 ConcurrentModificationException
    • 实现差异ArrayList 的 Itr 直接操作数组索引,LinkedList 的 ListItr 基于链表节点双向遍历。

(三)增强 for + Lambda:遍历的语法糖进化

  • 增强 for:本质是 Iterator 的语法糖(自动创建迭代器),简化代码但 不支持索引操作
  • Lambda + forEach:结合 Collection.forEach(Consumer),利用函数式接口实现极简遍历(如 list.forEach(System.out::println)),底层仍依赖迭代器。

(四)List 接口:有序集合的精细化操作

  • 特有方法:索引操作(get(int)add(int, E)remove(int))、双向迭代器 ListIterator(支持 previous() 反向遍历、中间修改);
  • 遍历对比

方式效率(ArrayList)效率(LinkedList)支持操作
普通 for✔️ O (1)(随机访问)❌ O (n)(遍历)索引控制
增强 for✔️ 语法糖❌ 遍历耗时简单遍历
Iterator✔️ 通用✔️ 链表友好删除操作
ListIterator✔️ 双向✔️ 双向中间插入 / 修改
Lambda forEach✔️ 极简❌ 遍历耗时无状态操作

(五)数据结构对比:数组 vs 链表 vs 栈 vs 队列

结构底层实现核心特性典型操作效率
数组连续内存随机访问快,增删中间慢get() O(1),add(中间) O(n)
链表离散节点(prev/next)增删头尾快,随机访问慢addFirst() O(1),get() O(n)
数组 / 链表后进先出(LIFO)push()/pop() O(1)
队列链表(如 LinkedList)先进先出(FIFO)offer()/poll() O(1)

(六)ArrayList 源码:动态数组的扩容艺术

  • 初始化:JDK 8+ 无参构造器初始为空数组,首次 add 时扩容为 10
  • 扩容策略:默认扩容 1.5 倍oldCapacity + (oldCapacity >> 1)),通过 Arrays.copyOf(native 方法)高效拷贝数组;
  • 性能陷阱:中间增删触发元素移动(O (n)),批量添加建议提前 ensureCapacity 减少扩容次数。

(七)LinkedList 与迭代器:双向链表的设计

  • 结构:内部类 Node<E> 存储元素及前后指针,头尾节点 first/last
  • 迭代器ListItr 维护当前节点、前一节点,支持双向遍历和中间修改;
  • 性能短板:遍历效率低于 ArrayList(链表节点分散,缓存不友好),适合 头尾高频增删 场景。

(八)泛型:类型安全的屏障

  • 核心概念:泛型类(List<E>)、泛型方法(<T> T func(T t))、通配符(? extends E 只读,? super E 可写);
  • 底层真相类型擦除(编译期替换为 Object 或边界类型),运行时无泛型信息,需通过反射或 @SuppressWarnings 处理类型转换。

(九)Map 接口:双列集合的键值映射

  • 核心特点:键唯一(equals+hashCode 约束),值可重复;支持 键找值、键值对遍历
  • 常用 APIputgetremovecontainsKeykeySetentrySet
  • 实现类差异
    • HashMap:哈希表(数组 + 链表 + 红黑树),无序,允许 null 键 / 值;
    • LinkedHashMap:继承 HashMap,内部维护 双向链表,保持 插入 / 访问顺序
    • TreeMap:红黑树实现,按键 自然排序 / 定制排序不允许 null 键

(十)Map 遍历的三重范式

  1. 键找值:遍历 keySet(),通过 get(key) 取值;
  2. 键值对:遍历 entrySet(),获取 Map.Entry<K,V>,同时操作键值;
  3. Lambda 遍历forEach(BiConsumer<K,V> action),代码极简(如 map.forEach((k,v) -> System.out.println(k+":"+v)))。

(十一)TreeMap 与自定义排序

  • 自然排序:键实现 Comparable 接口,重写 compareTo
  • 定制排序:创建 TreeMap 时传入 Comparator,优先级高于自然排序(如按字符串长度排序)。

(十二)HashMap 源码核心:哈希与扩容

  • 哈希计算key.hashCode() ^ (key.hashCode() >>> 16),减少高位冲突;
  • 扩容机制:初始容量 16,负载因子 0.75,扩容时容量 翻倍;链表转红黑树(阈值 8,且数组容量≥64);
  • 哈希冲突链地址法,链表节点超过 8 转为红黑树,查询效率从 O (n) 提升至 O (logn)。

二、实践突破:集合的场景化应用

(一)ArrayList 扩容验证(反射揭秘容量变化)

java

public class ArrayListCapacity {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();for (int i = 0; i < 20; i++) {list.add(i);System.out.println("size: " + list.size() + ", capacity: " + getCapacity(list));}}private static int getCapacity(ArrayList<?> list) {try {Field field = ArrayList.class.getDeclaredField("elementData");field.setAccessible(true);return ((Object[]) field.get(list)).length;} catch (Exception e) {e.printStackTrace();return 0;}}
}
// 输出:首次 add 后容量 10,满后扩容 15(10→15→22...),验证 1.5 倍扩容逻辑

(二)LinkedList 性能对比(头尾 vs 中间操作)

java

public class LinkedListPerfTest {public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();// 头尾操作(O(1),极快)long start = System.currentTimeMillis();for (int i = 0; i < 100000; i++) {list.addFirst(i); // 或 addLast}System.out.println("头尾操作耗时:" + (System.currentTimeMillis() - start) + "ms");// 中间插入(O(n),极慢)start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {list.add(50000, i); // 中间位置插入}System.out.println("中间插入耗时:" + (System.currentTimeMillis() - start) + "ms");}
}
// 结论:头尾操作高效,中间插入因遍历节点耗时剧增

(三)迭代器 fail-fast 演示(并发修改异常)

java

public class FailFastDemo {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));Iterator<String> it = list.iterator();while (it.hasNext()) {String s = it.next();if ("B".equals(s)) {// list.remove(s); // 非迭代器删除,触发 ConcurrentModificationExceptionit.remove(); // 正确方式:通过迭代器删除,避免异常}}System.out.println(list); // 输出:[A, C]}
}

(四)泛型通配符实践(读写边界控制)

java

// 泛型类
class Box<T> { private T value; public T get() { return value; }public void set(T value) { this.value = value; }
}public class GenericWildcard {public static void main(String[] args) {Box<Integer> intBox = new Box<>();intBox.set(10);Box<Double> doubleBox = new Box<>();doubleBox.set(3.14);printBox(intBox);  // 上限通配符:接受 Number 及其子类(如 Integer)addNumber(doubleBox); // 下限通配符:接受 Double 及其父类(如 Number、Object)}// 只读:只能 get,不能 set(除 null)public static void printBox(Box<? extends Number> box) {System.out.println(box.get()); // 合法:Number 类型// box.set(20); // 非法:无法确定具体类型}// 可写:只能 set 子类实例(如 Double)public static void addNumber(Box<? super Double> box) {box.set(2.718); // 合法:Double 是 ? super Double 的子类型// box.set(10); // 非法:Integer 不是 Double 的父类}
}

(五)HashMap 存储自定义对象(键唯一验证)

java

class Student {String id;public Student(String id) { this.id = id; }@Overridepublic int hashCode() { return id.hashCode(); }@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(id, student.id);}
}public class HashMapCustomObject {public static void main(String[] args) {HashMap<Student, String> map = new HashMap<>();map.put(new Student("001"), "Alice");map.put(new Student("001"), "Bob"); // 覆盖,因 id 相同System.out.println(map.size()); // 输出:1}
}

(六)TreeMap 定制排序(按字符串长度排序)

java

public class TreeMapCustomSort {public static void main(String[] args) {TreeMap<String, Integer> map = new TreeMap<>((a, b) -> {int lenCompare = a.length() - b.length();return lenCompare != 0 ? lenCompare : a.compareTo(b);});map.put("Apple", 10);map.put("Banana", 5);map.put("Cherry", 8);map.forEach((k, v) -> System.out.println(k + ": " + v));// 输出:Apple:10, Banana:5, Cherry:8(长度 3、6、6,字典序 Banana < Cherry)}
}

(七)斗地主项目:集合嵌套与发牌逻辑

  1. 数据结构
    • Map<Integer, String>:序号→牌面(如 1→♠354→大王);
    • List<Integer>:存储所有牌的序号,用于 洗牌
    • TreeSet<Integer>:玩家手牌(自动排序,方便展示)。
  2. 核心步骤
    • 初始化牌:静态代码块生成 54 张牌的序号和牌面,存入 Map 和 List
    • 洗牌:Collections.shuffle(list)
    • 发牌:遍历 list,按索引分配给 底牌、玩家 1、2、3TreeSet 自动排序);
    • 展示:遍历 TreeSet,通过 Map 获取牌面展示。

三、底层原理:集合的运行机制解析

(一)Collection 接口的设计思想

  • 依赖倒置:业务代码依赖 Collection 接口,而非具体实现(如 ArrayList),便于切换存储结构(如 ArrayList → LinkedList);
  • 开闭原则:新增集合类型(如 CopyOnWriteArrayList)只需实现接口,不影响上层逻辑。

(二)迭代器 fail-fast 的实现

  • ArrayList 内部维护 modCount(每次增删操作自增);
  • 迭代器创建时记录 expectedModCount = modCount
  • 每次 next()/remove() 时校验 expectedModCount == modCount,不等则抛 ConcurrentModificationException,快速暴露并发问题。

(三)ArrayList 扩容的底层逻辑

  • 内存拷贝Arrays.copyOf 调用 native 方法,直接操作内存块,比 Java 循环拷贝快 3~5 倍;
  • 扩容触发:当 size == capacity 时触发,空构造器首次 add 会初始化容量为 10;
  • 内存碎片:频繁扩容可能导致内存浪费,建议通过 ensureCapacity 预分配空间。

(四)LinkedList 的链表模型

  • 节点内存:每个 Node 占 3 个引用(itemprevnext),内存分散,缓存命中率低(对比 ArrayList 的连续数组);
  • 头尾操作:直接修改 first/last 指针,时间复杂度 O (1);中间操作需遍历节点,时间复杂度 O (n)。

(五)泛型的类型擦除

  • 编译期处理List<String> 编译后变为 List<Object>,泛型信息仅用于编译期类型检查;
  • 运行时陷阱:反射获取泛型类型需通过 TypeToken(如 Gson 反序列化),否则会丢失类型信息。

(六)HashMap 哈希冲突与红黑树转换

  • 链地址法:数组每个桶存链表头节点,冲突时链表追加;
  • 链表转红黑树:当桶内链表长度≥8,且数组容量≥64 时,链表转为红黑树(TreeNode),查询效率从 O (n) 提升至 O (logn);
  • 扩容时:旧数组元素重新哈希到新数组,链表节点可能拆分到不同桶,红黑树则拆分为链表或保持树结构。

(七)TreeMap 红黑树原理

  • 自平衡二叉搜索树,确保左右子树高度差≤1,查询 / 插入 / 删除均为 O (logn);
  • 节点颜色:红或黑,通过 旋转和变色 保持平衡,保证有序性。

(八)LinkedHashMap 双向链表

  • 继承 HashMap,内部维护 header 双向链表,记录 插入顺序(或访问顺序,开启 accessOrder);
  • 遍历时按链表顺序,比 HashMap 的无序遍历更高效(如需按插入顺序处理)。

(九)集合嵌套的内存模型(以斗地主为例)

  • Map 存储序号和牌面的映射,List 存储序号(洗牌的载体),TreeSet 存储玩家手牌(自动排序);
  • 内存关联:TreeSet 中的序号指向 Map 中的牌面,实现 “序号→牌面” 的关联展示。

四、总结与展望:从 “会用” 到 “精通” 的进阶

今日突破:

  • 技术维度:贯通 Collection(单列) 与 Map(双列) 体系,掌握迭代器、泛型、数据结构对比、源码分析(ArrayList/LinkedList/HashMap/TreeMap),结合斗地主项目实践 集合嵌套
  • 实践细节:规避 ArrayList 扩容陷阱、LinkedList 中间操作低效、迭代器删除异常、泛型通配符读写限制,掌握 Map 键唯一性(hashCode/equals)、TreeMap 排序策略、HashMap 扩容与红黑树转换触发条件;
  • 底层认知:接口解耦思想、fail-fast 实现、动态数组扩容算法、链表内存模型、泛型类型擦除、哈希冲突解决、红黑树平衡机制、集合嵌套关联逻辑。

后续规划:

技术深化:
  • 并发集合:剖析 ConcurrentHashMap(CAS + synchronized 替代分段锁)、CopyOnWriteArrayList(读写分离)的线程安全实现;
  • Map 源码攻坚HashMap 扩容全流程、TreeMap 红黑树旋转细节、LinkedHashMap 链表维护;
  • 集合工具类Collections.sort(归并排序优化)、同步集合(synchronizedMap)、不可变集合(ImmutableList);
  • 泛型高级Map<K,V> 的通配符(? extends K 只读键,? super V 可写值)、自定义泛型映射。
设计模式融合:
  • 工厂模式:封装集合创建(如根据需求选 HashMap/TreeMap);
  • 策略模式TreeMap 的 Comparator 作为排序策略,动态切换;
  • 适配器模式:将 Map 转换为 List(如 entrySet 转 List 进行排序)。
工程化实践:
  • 性能优化HashMap 初始容量计算(避免频繁扩容)、TreeMap 排序开销权衡、LinkedHashMap 访问顺序优化;
  • 线程安全:区分 Hashtable(全锁)、ConcurrentHashMap(分段锁)的适用场景;
  • 单元测试Map 键冲突测试、TreeMap 排序异常测试、集合嵌套的空指针防护;
  • 异常处理HashMap 的 null 键处理、TreeMap 的 null 键异常(非 Comparable 时)。
细节攻坚:
  • 优化 HashMap:通过 initialCapacity 和 loadFactor 减少扩容次数,避免链表转红黑树的性能波动;
  • 深入红黑树:手动模拟 TreeMap 的插入和旋转过程,理解平衡机制;
  • 集合嵌套调试:斗地主项目中牌序异常(如 TreeSet 排序不符合预期)的排查方法;
  • 泛型与 Map:解决 JSON 反序列化时 Map 泛型类型丢失问题(结合 TypeToken)。

持续在 “接口规范 → 实现细节 → 源码分析 → 工程优化” 的闭环中迭代,不仅掌握集合的表层用法,更深入理解 哈希、红黑树、链表 等底层数据结构,以及 并发、泛型、设计模式 的融合应用,为 高并发缓存、有序数据存储、复杂集合嵌套逻辑 等业务场景提供高效解决方案 ✨。

http://www.dtcms.com/a/278673.html

相关文章:

  • Ubuntu安装Mongodb
  • 《甘肃棒球》国家级运动健将标准·棒球1号位
  • 九、官方人格提示词汇总(下)
  • OpenCV 视频处理与摄像头操作详解
  • 面试题--xxl-job分布式任务调度
  • 全面解析WOFOST与PCSE农作物生长模型;农作物生长和产量预测
  • 基于esp32系列的开源无线dap-link项目使用介绍
  • 空间智能-李飞飞团队工作总结(至2025.07)
  • 【工具】AndroidStudio修改中文语言汉化
  • Python数据容器-通用功能
  • 九、官方人格提示词汇总(中-1)
  • Usage of standard library is restricted (arkts-limited-stdlib) <ArkTSCheck>
  • 【leetcode】231. 2的幂
  • 13.7 Meta LLaMA2-Chat核心技术突破:三重强化学习实现91.4%安全评分,超越ChatGPT的对话模型架构全解析
  • React 第六十九节 Router中renderMatches的使用详解及注意事项
  • 文档处理控件Aspose.Words教程:从 C# 中的 Word 文档中提取页面
  • 汽车工件工艺追溯管理系统软件设计(草稿)
  • 我的Qt八股文面试笔记1:信号与槽文件流操作
  • 持续优化小程序排名,稳定获取搜索流量
  • 【世纪龙科技】迈腾B8汽车整车检测与诊断仿真实训系统
  • vue中配置Eslint的步骤
  • 【世纪龙科技】汽车整车检测与诊断仿真实训系统-迈腾B8
  • Redis随笔
  • 算法学习笔记:21.动态规划——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • Qt小组件 - 2(布局)瀑布流布局,GridLayout,FlowLayout
  • QT跨平台应用程序开发框架(7)—— 常用输入类控件
  • [Dify] -基础入门10- Dify 应用开发与 ChatGPT 的区别与优势分析
  • Sharding-Sphere学习专题(四)广播表和绑定表、分片审计
  • 【王树森推荐系统】物品冷启05:流量调控
  • ether.js—6—contractFactory以部署ERC20代币标准为例子