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

11_Java集合框架概述

Java集合框架概述 —— Collection与Map体系全解析

文章目录

  • Java集合框架概述 —— Collection与Map体系全解析
    • 前言
    • 一、Java集合框架的体系结构
    • 二、Collection接口详解
      • 2.1 Collection核心方法
      • 2.2 List接口
      • 2.3 Set接口
      • 2.4 Queue接口
    • 三、Map接口详解
      • 3.1 Map核心方法
      • 3.2 HashMap使用示例
    • 四、迭代器详解
      • 4.1 迭代器的三个核心方法
      • 4.2 迭代过程中安全删除元素
      • 4.3 增强for循环的本质
    • 五、迭代器模式的设计思想
      • 设计模式实践
    • 六、集合的选择策略
    • 总结
    • ✅ 亮点总结
    • 适用场景
    • 扩展方向

前言

在Java开发中,数据的存储与操作是永恒的核心话题。无论是处理用户列表、缓存数据,还是构建复杂的数据结构,都离不开集合框架的支持。Java集合框架(Java Collections Framework,简称JCF)是JDK提供的一套设计精良的数据结构工具库,理解它的体系结构对于写出高效、优雅的Java代码至关重要。

集合框架的核心设计思想是接口与实现分离——所有的集合操作都通过接口(如List、Set、Map)来定义规范,不同的实现类(如ArrayList、LinkedList、HashMap)提供不同的底层数据结构和性能特征。这种设计让你可以在不修改调用代码的情况下切换实现类:比如从ArrayList换成LinkedList,只需修改一行new语句,其余代码保持不变。这种灵活性正是面向接口编程的最佳体现。

本文将带你从整体上把握Java集合框架的体系结构,理解Collection和Map两大接口体系,并掌握迭代器的使用方式。这篇文章是后续ArrayList/LinkedList对比和HashMap深度解析两篇文章的基础铺垫。

一、Java集合框架的体系结构

Java集合框架主要分为两大接口体系:CollectionMap。这个划分非常清晰——Collection是"单列数据"的抽象(一条一条的元素),Map是"键值对数据"的抽象(Key→Value的映射关系)。两者是并列关系而非继承关系——Map不是Collection的子接口,这一点在面试中经常被用来制造陷阱。

  • Collection接口:存储单个元素,是List、Set、Queue的父接口
  • Map接口:存储键值对(Key-Value),与Collection接口是并列关系

整体继承关系如下:

Collection (接口) ├── List (接口) —— 有序、可重复 │ ├── ArrayList │ ├── LinkedList │ └── Vector (已基本淘汰) ├── Set (接口) —— 无序、不可重复 │ ├── HashSet │ ├── LinkedHashSet │ └── TreeSet └── Queue/Deque (接口) —— 队列/双端队列 ├── LinkedList ├── ArrayDeque └── PriorityQueue Map (接口) —— 键值对 ├── HashMap ├── LinkedHashMap ├── TreeMap └── Hashtable (已基本淘汰)

下面通过一个简单的示例来感受不同集合的特点:

importjava.util.*;publicclassCollectionOverview{publicstaticvoidmain(String[]args){// List:有序可重复List<String>list=newArrayList<>();list.add("Java");list.add("Python");list.add("Java");// 允许重复System.out.println("List: "+list);// [Java, Python, Java]// Set:无序不可重复Set<String>set=newHashSet<>();set.add("Java");set.add("Python");set.add("Java");// 重复元素不会添加System.out.println("Set: "+set);// [Java, Python] 或 [Python, Java]// Map:键值对Map<String,Integer>map=newHashMap<>();map.put("Java",1995);map.put("Python",1991);map.put("Java",1996);// 覆盖旧值System.out.println("Map: "+map);// {Java=1996, Python=1991}}}

二、Collection接口详解

Collection是List、Set、Queue的最高父接口,定义了集合操作的通用方法。

2.1 Collection核心方法

publicinterfaceCollection<E>extendsIterable<E>{intsize();// 返回元素个数booleanisEmpty();// 判断是否为空booleancontains(Objecto);// 是否包含某元素booleanadd(Ee);// 添加元素booleanremove(Objecto);// 移除元素voidclear();// 清空集合Iterator<E>iterator();// 获取迭代器Object[]toArray();// 转换为数组// ... 还有其他方法}

2.2 List接口

List是有序集合,可以通过索引访问元素。核心特点:有序、可重复、有索引。

publicclassListDemo{publicstaticvoidmain(String[]args){List<String>list=newArrayList<>();list.add("A");list.add("B");list.add("C");// 索引访问System.out.println(list.get(1));// B// 在指定位置插入list.add(1,"X");System.out.println(list);// [A, X, B, C]// 遍历方式for(inti=0;i<list.size();i++){System.out.print(list.get(i)+" ");// A X B C}}}

2.3 Set接口

Set不允许重复元素,主要用于去重场景。判断重复依赖**equals()hashCode()**方法。

publicclassSetDemo{publicstaticvoidmain(String[]args){Set<String>set=newHashSet<>();set.add("apple");set.add("banana");set.add("apple");// 不会添加System.out.println(set.size());// 2// TreeSet 实现排序Set<Integer>sortedSet=newTreeSet<>();sortedSet.add(5);sortedSet.add(1);sortedSet.add(3);System.out.println(sortedSet);// [1, 3, 5] 自动排序}}

2.4 Queue接口

Queue模拟队列数据结构,遵循FIFO(先进先出)原则。在Java中,Queue是一个接口,LinkedList是它最常用的实现(同时实现了List和Deque)。理解Queue的API设计模式很重要,因为它体现了Java集合框架的一个设计惯例——用不同返回值处理不同错误场景

操作抛出异常返回特殊值
入队add(e)offer(e)→ false
出队remove()poll()→ null
查看队首element()peek()→ null

这种"双API"设计让你可以根据场景选择:如果队列为空是你预料之内的情况,用poll()返回null更优雅;如果队列应该永远非空,用remove()让异常暴露问题更合适。

publicclassQueueDemo{publicstaticvoidmain(String[]args){Queue<String>queue=newLinkedList<>();queue.offer("A");// 入队queue.offer("B");queue.offer("C");System.out.println(queue.poll());// A 出队并移除System.out.println(queue.peek());// B 查看队首不移除System.out.println(queue);// [B, C]}}

三、Map接口详解

Map存储键值对(Key-Value),每个Key最多映射一个Value。

3.1 Map核心方法

publicinterfaceMap<K,V>{Vput(Kkey,Vvalue);// 添加键值对Vget(Objectkey);// 根据Key获取ValueVremove(Objectkey);// 根据Key移除booleancontainsKey(Objectkey);// 是否包含KeybooleancontainsValue(Objectvalue);// 是否包含ValueSet<K>keySet();// 获取所有Key的Set集合Collection<V>values();// 获取所有Value的CollectionSet<Map.Entry<K,V>>entrySet();// 获取所有键值对// ...}

3.2 HashMap使用示例

publicclassMapDemo{publicstaticvoidmain(String[]args){Map<String,Integer>map=newHashMap<>();map.put("张三",85);map.put("李四",92);map.put("王五",78);// 遍历方式1:通过keySetfor(Stringkey:map.keySet()){System.out.println(key+" -> "+map.get(key));}// 遍历方式2:通过entrySet(推荐,效率更高)for(Map.Entry<String,Integer>entry:map.entrySet()){System.out.println(entry.getKey()+" -> "+entry.getValue());}// 遍历方式3:forEach(Java 8+)map.forEach((key,value)->System.out.println(key+" -> "+value));}}

四、迭代器详解

Iterator是遍历集合的统一方式,所有Collection的子类都可以通过iterator()获取迭代器。

4.1 迭代器的三个核心方法

publicclassIteratorDemo{publicstaticvoidmain(String[]args){List<String>list=newArrayList<>();list.add("Java");list.add("Python");list.add("C++");Iterator<String>iterator=list.iterator();while(iterator.hasNext()){Stringelement=iterator.next();System.out.println(element);}}}
  • hasNext():判断是否还有下一个元素
  • next():返回当前元素并将指针后移
  • remove():移除上次next()返回的元素

4.2 迭代过程中安全删除元素

遍历集合时,如果直接用集合的remove()方法删除元素,会抛出ConcurrentModificationException。这是因为集合内部有一个modCount计数器,每次结构性修改都会自增,而迭代器在创建时会记录当时的modCount值,每次next()时检查是否一致。如果直接用集合的remove()(会修改modCount),迭代器的检查就会失败——这是一种**fail-fast(快速失败)**机制,用于尽早暴露并发修改问题。

正确做法是使用迭代器的remove()方法,它会同步更新自己的expectedModCount。JDK 8还提供了更简洁的removeIf()方法,内部也是基于迭代器实现。

publicclassSafeRemoveDemo{publicstaticvoidmain(String[]args){List<String>list=newArrayList<>();list.add("Java");list.add("Python");list.add("C++");// 错误做法:会抛出ConcurrentModificationException// for (String s : list) {// if ("Python".equals(s)) {// list.remove(s); // 危险!// }// }// 正确做法:使用迭代器的remove()Iterator<String>it=list.iterator();while(it.hasNext()){Strings=it.next();if("Python".equals(s)){it.remove();// 安全删除}}System.out.println(list);// [Java, C++]}}

4.3 增强for循环的本质

增强for循环(foreach)实际上是迭代器的语法糖,编译后等价于使用Iterator遍历:

// 源码写法for(Strings:list){System.out.println(s);}// 编译后等价于for(Iterator<String>it=list.iterator();it.hasNext();){Strings=it.next();System.out.println(s);}

五、迭代器模式的设计思想

迭代器模式的精髓在于将遍历行为从集合本身分离出来。这样做的好处是:

  1. 解耦:遍历算法与集合的实现分离
  2. 统一接口:无论底层是数组还是链表,遍历方式都一样
  3. 封装内部结构:调用者无需知道集合的内部实现

设计模式实践

// 使用ListIterator实现双向遍历(仅List实现支持)publicclassListIteratorDemo{publicstaticvoidmain(String[]args){List<String>list=newArrayList<>();list.add("一");list.add("二");list.add("三");ListIterator<String>listIterator=list.listIterator();// 正向遍历while(listIterator.hasNext()){System.out.print(listIterator.next()+" ");// 一 二 三}System.out.println();// 反向遍历while(listIterator.hasPrevious()){System.out.print(listIterator.previous()+" ");// 三 二 一}}}

六、集合的选择策略

在实际开发中,选择合适的集合类型非常重要,这直接影响程序的性能和可读性。以下是一些选择建议:

需求场景推荐集合
需要快速随机访问ArrayList
频繁插入删除LinkedList
需要去重HashSet
需要排序TreeSet / TreeMap
需要键值对HashMap
线程安全场景ConcurrentHashMap / CopyOnWriteArrayList
按插入顺序遍历LinkedHashMap / LinkedHashSet

总结

本文介绍了Java集合框架的整体架构,涵盖了Collection和Map两大接口体系,以及迭代器的使用方式。集合框架是Java中最常用的工具库,可以说任何Java项目都离不开它。以下是本文的核心收获:

  • Collection体系:List(有序可重复,适合按索引操作)、Set(无序不可重复,适合去重)、Queue(FIFO队列,适合任务调度)三大子接口各有专攻
  • Map体系:键值对存储,HashMap是最常用的实现,TreeMap适合排序场景,LinkedHashMap适合按插入顺序遍历
  • Iterator迭代器:统一的遍历接口,将遍历逻辑与底层数据结构解耦。增强for循环本质是迭代器的语法糖
  • fail-fast机制ConcurrentModificationException是集合的"安全阀",防止在遍历过程中被意外修改导致数据不一致

掌握这些基础知识后,在后续文章中我们将深入探讨ArrayList和LinkedList的底层原理、HashMap的哈希表实现、以及多线程环境下的并发集合等高级话题。集合框架的真正功力体现在选型能力上——同样是存储100万条数据,选ArrayList还是LinkedList?选HashMap还是TreeMap?这取决于你对底层数据结构的理解深度。

Java集合框架的设计充分体现了接口与实现分离、抽象层次分明的设计思想。理解这套框架,对于一个Java开发者来说不仅是面试的必备知识,更是写出高质量代码的基础。

✅ 亮点总结

  • Collection与Map两大体系划分:Collection存储单列数据(List/Set/Queue),Map存储键值对(HashMap/TreeMap),用一张全景图理清所有集合类的归属
  • Iterator迭代器模式的优雅设计:将遍历行为与底层数据结构解耦,无论ArrayList数组还是LinkedList链表,hasNext()/next()接口完全统一
  • ListIterator的双向遍历能力:相比普通Iterator只能"前进",ListIterator支持"后退"(hasPrevious()/previous()),适合需要双向操作的场景
  • 集合选择速查表:一张表格将"需随机访问→ArrayList"、“需去重→HashSet”、"需排序→TreeMap"等常见场景一一对应,减少选型犹豫
  • 接口与实现分离的设计思想List<String> list = new ArrayList<>()——声明用接口,实现选具体类,这是面向接口编程的经典实践

适用场景

  • 全局搜索项目中所有使用List的地方,检查是否选择了正确的实现类(是否滥用LinkedList或漏用HashSet去重)
  • 处理从数据库或API返回的批量数据时,根据后续操作(遍历/随机访问/去重/排序)选择合适的集合类型
  • 重构代码时,将for (int i = 0; i < list.size(); i++)统一替换为增强for循环或迭代器,提升代码可读性

扩展方向

  • ArrayList vs LinkedList深度对比:理解两者底层数据结构和时间复杂度差异,做出最优选型,推荐阅读 12_ArrayList与LinkedList深度对比
  • HashMap底层原理:数组+链表+红黑树的哈希表实现,JDK 1.7到1.8的演进故事,推荐阅读 13_HashMap底层原理详解
  • 并发集合ConcurrentHashMap的分段锁机制、CopyOnWriteArrayList的写时复制策略,理解多线程环境下的集合安全方案

下一篇:12_ArrayList与LinkedList深度对比

http://www.cnnetsun.cn/news/2722853.html

相关文章:

  • HoloLens混合现实应用开发实战:从工业设计到远程协作的四大核心场景
  • AI产品设计:从可用到好用的系统性设计思维与实践
  • 全栈开发硬核命题,拒绝CRUD男孩
  • UE5 VR开发避坑指南:Interaction组件里的Component Identification到底怎么用?
  • 类别不平衡问题
  • SNAP 9.0处理Sentinel-1 SLC数据:一个简化流程的避坑实践(跳过Split/Merge)
  • Redis中间件综合技术分析
  • 保姆级避坑指南:手把手教你用mmWave Studio 2.0搞定AWR1843雷达数据采集(从接线到.bin文件生成)
  • 配置存储卷
  • 别再只会用默认字符集了!Kali Linux中crunch的-f参数实战:调用内置字符库生成高命中率字典
  • 大模型如何提升代码质量与数据洞察:微软前沿研究解析与实践指南
  • FreeRTOS 任务调度机制剖析:优先级抢占、时间片轮转与上下文切换的汇编实现
  • [ACTF2020 新生赛]Exec
  • 杰理工程师日志2: 杰理蓝牙芯片音箱类方案开发添加提示音的具体操作指导说明
  • 树莓派玩家的后悔药:用Balena Etcher一键克隆和备份你的完整系统(含SD卡扩容后备份技巧)
  • Azure云上构建弹性HPC集群:从InfiniBand网络到Slurm调度的超级计算实践
  • GEE Assets权限管理详解:如何安全共享你的数据,以及调用他人公开Assets的正确姿势
  • 【AI笔记】短时纯音时长对音高感知偏移效应研究综述
  • 从‘通才’到‘专精’:聊聊大语言模型(LLM)微调中的终身学习困境与实战策略
  • YOLOv8魔改笔记:把C2f换成CSPStage,再加个检测头,我的GC10-DET缺陷识别项目效果起飞了
  • 从大数据到深数据:云计算与交互技术如何赋能文化遗产数字化
  • Verilog边沿检测电路实战:从原理到仿真,手把手教你搞定上升沿、下降沿和双沿检测
  • YOLOv11红外+可见光双路检测工具包:开箱即用的多模态目标识别方案
  • 避坑指南:UR3+Realsense手眼标定中,如何解决ArUco标记识别与采样不足(0/17)的问题
  • 2026年优质AIGC社区盘点,兼顾创作与观赏
  • 保姆级教程:用ZStack Cloud 4.6.31在Linux上快速搭建私有云(附虚拟化引擎避坑指南)
  • 电路设计与PCB制作全流程:从原理图到焊接调试实战指南
  • 微信小程序登录页和主页隐藏返回按钮的完整配置流程(wx.reLaunch + onShow实战)
  • 从关键词匹配到任务理解:下一代搜索引擎如何实现智能信息推理与整合
  • Revizor:自动化挖掘CPU推测执行漏洞的硬件安全测试框架