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

从”0“开始学JAVA——第九节下 泛型和集合框架

        上一节我们介绍了泛型的概念、集合框架的两大根接口——Collection(单列集合)接口、Map(双列集合)接口,以及Collection接口下的两个重要的子接口——List接口和Set接口,除此之外还举例了这几个接口的常用方法。

        那么这一节,我们一起来了解一下List接口、Set接口、Map接口下的几个常用实现类以及TreeSet中的两种排序方法——Comparable(自然排序)、Comparator(比较器排序):

第一部分:List接口下的实现类

1. ArrayList
  • 特点特性

    • 底层实现:基于动态数组Object[] elementData)。

    • 线程安全。非同步,多线程环境下不安全。

    • 元素访问:支持随机访问(通过索引),实现了 RandomAccess 标记接口。

    • 扩容机制:当数组容量不足时,会自动扩容(通常是增加为原来的1.5倍)。这是一个相对耗时的操作。

  • 优点

    • 查询效率高get(int index)set(int index, E element))。因为数组在内存中是连续存储的,通过索引可以直接计算出内存地址,时间复杂度为 O(1)

  • 缺点

    • 增删效率较低(除非在尾部操作)。在列表中间进行插入(add(int index, E element))或删除(remove(int index))操作时,需要移动后续的所有元素,平均时间复杂度为 O(n)

  • 适用场景

    • 查询操作远多于增删操作的场景。

    • 例如:商品列表展示、配置文件读取、学生管理系统(学期开始录入后,主要以查询为主)。

2. LinkedList
  • 特点特性

    • 底层实现:基于双向链表数据结构。

    • 线程安全

    • 元素访问:不支持高效随机访问。需要从链表头或尾开始遍历,平均时间复杂度为 O(n)

  • 优点

    • 增删效率高。在已知位置(例如通过listIterator获得的位置)进行插入和删除操作,只需要修改相邻节点的指针,时间复杂度为 O(1)。特别适合在列表中间进行频繁的增删。

    • 天然支持队列操作。实现了 Deque 接口,可以很方便地作为栈、队列、双端队列使用。

  • 缺点

    • 查询效率低。按索引访问元素需要遍历,时间复杂度为 O(n)

    • 内存占用略高,因为每个节点都需要存储前后节点的指针。

  • 适用场景

    • 增删操作远多于查询操作的场景。

    • 需要实现队列、栈等数据结构。

    • 例如:浏览器的前进后退历史记录、消息队列、LRU缓存。

3. Vector
  • 特点特性

    • 底层实现:和 ArrayList 一样,基于动态数组。

    • 线程安全。其几乎所有方法都使用了 synchronized 关键字修饰,保证了同步访问。

  • 优点

    • 线程安全。

  • 缺点

    • 性能低下。由于方法同步带来的锁开销,效率远低于 ArrayList

    • 作为早期JDK的类,其API设计不够现代(如枚举遍历)。

  • 适用场景

    • 已过时,不推荐在新代码中使用。

    • 如果需要线程安全的列表,应使用 Collections.synchronizedList(new ArrayList<>()) 或 java.util.concurrent.CopyOnWriteArrayList

实现类直接继承的类直接实现的接口
ArrayListAbstractListListRandomAccess(标记接口), Cloneablejava.io.Serializable
LinkedListAbstractSequentialList(而它又继承自 AbstractListListDequeCloneablejava.io.Serializable
VectorAbstractListListRandomAccess(标记接口), Cloneablejava.io.Serializable

第二部分:Set接口下的实现类

1. HashSet
  • 特点特性

    • 底层实现:基于 HashMap 实现,实际上就是使用 HashMap 的 Key 来存储元素,Value 是一个固定的 Object 常量。

    • 元素顺序不保证顺序,特别是它不保证顺序恒久不变。

    • 线程安全

    • 允许元素:允许 null 元素。

  • 优点

    • 添加、删除、查找(addremovecontains)效率极高,时间复杂度为 O(1)。性能是 Set 实现中最好的。

  • 缺点

    • 无序。

  • 适用场景

    • 需要快速去重不关心元素顺序的场合。

    • 例如:存储黑名单ID、快速判断某个元素是否存在。

2. LinkedHashSet
  • 特点特性

    • 底层实现:继承自 HashSet,但基于 LinkedHashMap 实现。

    • 元素顺序维护了一个运行于所有条目的双向链表,保证了元素的插入顺序(Insertion-Order)

    • 线程安全

  • 优点

    • 既拥有了 HashSet 的查询效率,又保证了迭代顺序

  • 缺点

    • 由于需要维护链表,性能略低于 HashSet,但迭代访问时比 HashSet 更快。

  • 适用场景

    • 需要去重,且需要保持元素添加顺序的场景。

    • 例如:缓存需要按访问顺序淘汰(可实现LRU)、记录用户操作序列(去重且有序)。

3. TreeSet
  • 特点特性

    • 底层实现:基于 TreeMap 实现,使用红黑树数据结构。

    • 元素顺序:元素不是按插入顺序排序,而是根据元素的自然顺序(实现 Comparable 接口)或者构造时提供的 Comparator(比较器) 进行排序。

    • 线程安全

    • 允许元素不允许 null 元素(取决于使用的比较器,如果使用自然排序,则不允许)。

  • 优点

    • 元素自动排序,并且提供了很多按顺序访问的方法(如 first()last()headSet()tailSet())。

  • 缺点

    • 添加、删除、查找操作的时间复杂度为 O(log n),比 HashSet 和 LinkedHashSet 慢。

  • 适用场景

    • 需要元素去重且自动排序的场景。

    • 例如:存储成绩列表并自动按分数从高到低排序、维护一个有序的单词列表。

实现类直接继承的类直接实现的接口
HashSetAbstractSetSetCloneablejava.io.Serializable
LinkedHashSetHashSet(它又继承自 AbstractSetSetCloneablejava.io.Serializable
TreeSetAbstractSetNavigableSet(而它又继承自 SortedSet

第三部分:Map接口下的实现类

1. HashMap
  • 特点特性

    • 底层实现:基于数组+链表+红黑树(JDK1.8+)。

    • 元素顺序不保证顺序

    • 线程安全

    • 允许键值:允许 null 键和 null 值。

  • 优点

    • 查询、插入、删除效率极高,在理想情况下(哈希函数均匀分布)时间复杂度为 O(1)。是最常用的 Map。

  • 缺点

    • 无序。

  • 适用场景

    • 绝大多数键值对存储场景,无需排序,无需线程安全。

    • 例如:存储用户ID和用户信息、Web请求参数键值对。

2. Hashtable
  • 特点特性

    • 底层实现:和 HashMap 类似,基于哈希表。

    • 线程安全。方法使用 synchronized 修饰。

    • 允许键值不允许 null 键或 null 值。

  • 优点

    • 线程安全。

  • 缺点

    • 性能低下,已过时。

  • 适用场景

    • 已过时,不推荐使用。替代方案是 ConcurrentHashMap

3. LinkedHashMap
  • 特点特性

    • 底层实现:继承自 HashMap,在其基础上增加了一条双向链表来维护所有 Entry 的顺序。

    • 元素顺序:默认按插入顺序(Insertion-Order) 迭代。如果在构造时指定 accessOrder 为 true,则会按访问顺序(Access-Order) 排序(LRU算法的基础)。

    • 线程安全

  • 优点

    • 保证了迭代顺序,迭代速度比 HashMap 快。

  • 缺点

    • 性能略低于 HashMap

  • 适用场景

    • 需要保持键值对插入顺序或访问顺序的场景。

    • 例如:实现 LRU(最近最少使用)缓存、记录操作日志(按时间顺序)。

4. TreeMap
  • 特点特性

    • 底层实现:基于红黑树

    • 元素顺序:根据键的自然顺序或构造时提供的 Comparator 进行排序。

    • 线程安全

    • 允许键值不允许 null 键(如果使用自然排序)。

  • 优点

    • 键自动排序,并提供了一系列基于顺序的导航方法(如 firstKey()lowerKey())。

  • 缺点

    • 操作的时间复杂度为 O(log n)

  • 适用场景

    • 需要按键排序的映射场景。

    • 例如:字典应用程序、按部门编号排序的员工信息。

实现类

直接继承的类直接实现的接口
HashMapAbstractMapMapCloneablejava.io.Serializable
LinkedHashMapHashMap(它又继承自 AbstractMapMap
HashtableDictionary(一个已过时的抽象类)MapCloneablejava.io.Serializable
TreeMapAbstractMapNavigableMap(而它又继承自 SortedMap

第四部分:TreeSet的排序机制详解

TreeSet 的所有排序功能都依赖于其底层的 TreeMap。要保证 TreeSet 能正确地对添加的元素进行排序,有两种方式:

1. 自然排序(Comparable)
  • 机制:让添加到 TreeSet 中的元素类实现 java.lang.Comparable 接口,并重写其 compareTo(Object o) 方法。该方法定义了对象之间的自然比较规则。

  • compareTo 方法重写规则

    • this(当前对象) > 参数对象 o:返回正整数

    • this == 参数对象 o:返回 0TreeSet 会认为这是重复元素,无法添加)

    • this < 参数对象 o:返回负整数

  • 示例:

Student基础类:

测试类:

运行结果:

2. 比较器排序(Comparator)
  • 机制:在创建 TreeSet 时,传入一个实现了 java.util.Comparator 接口的比较器对象。该方式更加灵活,它不需要修改元素类本身,并且可以为同一个类定义多种不同的排序规则。

  • compare 方法重写规则

    • 参数 o1 > 参数 o2:返回正整数

    • o1 == o2:返回 0

    • o1 < o2:返回负整数

  • 示例:

Student基础类:

测试类:

运行结果:

特性自然排序 (Comparable)比较器排序 (Comparator)
耦合度,排序规则定义在类内部,排序规则定义在类外部
灵活性,一个类只能有一种自然顺序,可以轻松创建多种不同的排序规则
适用场景类有明显的、唯一的自然顺序(如StringInteger1. 类没有实现Comparable
2. 想覆盖类的自然顺序
3. 需要为同一个类提供多种排序方式

总结:优先考虑使用 Comparator,因为它更灵活,对代码的侵入性更小。

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

相关文章:

  • #运维 | 前端 # Linux http.server 实践:隐藏长文件名,简短路径 (http://IP:port/别名 ) 访问
  • AI研究引擎的简单技术实现步骤
  • Web 安全之 HTTP 响应截断攻击详解
  • JavaScript 系列之:图片压缩
  • 微信小程序设计的请求封装方案(request.js)
  • NPM模块化总结
  • DINOv3 重磅发布
  • 计算机网络技术学习-day6《三层交换机配置》
  • python发布文章和同步文章到社区的工具小脚本
  • 第三阶段数据库-6:sql中函数,多表查询,运算符,索引,约束
  • 智慧城管云平台源码,微服务vue+element+springboot+uniapp技术架构,数字化综合执法办案系统
  • 数据结构之排序大全(4)
  • 苷类成分通过 PI3K/AKT 信号通路促进内皮祖细胞来源外泌体修复受损血管内皮
  • 基于YOLO11的茶叶病害智能检测系统
  • 组态软件——工业监控“大脑”
  • leetcode-python-242有效的字母异位词
  • 代码随线录刷题Day39
  • 【uni-app】自定义导航栏以及状态栏,胶囊按钮位置信息的获取
  • Java的运行时数据区
  • Notepad++换行符替换
  • 机器学习——AdaBoost算法
  • 基于YOLO11的水稻叶片病害检测项目
  • 面试压力测试破解:如何从容应对棘手问题与挑战
  • (第二十期上)HTML 超链接标签 a
  • 【工具】前端JS/VUE修改图片分辨率
  • C语言数据结构:动态顺序表实现与应用
  • 如何使用Prometheus + Grafana + Loki构建一个现代化的云原生监控系统
  • 数字社会学是干什么的?数字社会学理论与数字社会学家唐兴通讲数字社会学书籍有哪些?AI社会学人工智能社会学理论框架
  • 4090服务器无法sudo apt update 问题解决
  • 告别服务器!Amazon Lambda无服务开发实战指南