java 数组笔记
发布日期:2021-05-18 04:44:01 浏览次数:23 分类:精选文章

本文共 2180 字,大约阅读时间需要 7 分钟。

Collection接口解析

List集合

ArrayList

ArrayList是最常用的实现类,其本质是一个动态大小的数组,具备以下特点:

  • 允许存放null元素
  • 初始容量为10,通过grow()方法动态扩展
  • 随机访问性能优异,适合使用数组索引快速获取元素
  • 插入和删除操作中,数组元素需要整体移动,导致性能相对较差
  • 扩容逻辑:新容量=原始容量 + (原始容量 > 0 ? oldCapacity / 2 : 0)

    LinkedList

    LinkedList基于双向链表实现,因其插入和删除操作性能优于ArrayList,但随机访问速度较慢。其主要特点包括:

  • 允许存放null元素
  • 双向链表结构,便于前后迭代
  • 不同于ArrayList,链表长度无需预先定义,可以扩展到任意长度
  • 支持并发访问,如实现Deque接口,可作为队列和栈使用
  • Vector与Stack

    • Vector: 基于数组实现,线程安全,与ArrayList兼容性较差,因其同步机制导致性能开销较大。
    • Stack: 继承自Vector,按先进后出原则管理元素,常用于临时存储。

    List的选择依据

  • 快速插入和删除: LinkedList优于ArrayList。
  • 快速随机访问: ArrayList优于LinkedList。
  • 线程安全要求: Vector线程安全,适用于多线程环境;CopyOnWriteArrayList实现非阻塞同步,性能优于Vector。
  • 单线程环境: 使用非同步类如ArrayList或LinkedList。
  • 高性能需求: ArrayList在查询效率上更优。
  • List总结

    • ArrayList: 适合icus架构和随机访问为主的场景。
    • LinkedList: 适合频繁插入删除,需要双向链表功能的场景。

    Map集合

    HashMap

    HashMap是基于数组+链表+红黑树的数据结构,具备以下特点:

  • 键值对快速访问: 通过 hashCode computing实现O(1)平均时间复杂度查找。
  • 动态扩容机制: 当元素数量超过阈值时,扩容至下一个2^n的倍数,确保性能。
  • 默认初始容量: 为16或可能为4,取决于具体实现。
  • 负载因子: 默认为0.75,决定何时触发扩容。
  • 扩容与初始值

    • 初始容量为16,在实际使用中扩容到32、64等。
    • 检查逻辑:size > capacity * loadFactor。

    元素存储逻辑

    • 贮存桶(数组位置),每桶可能包含链表或红黑树。
    • 链表:存储8个或更多节点后转为红黑树,以减少查询开销。

    快速查找原理

    • 利用hashCode计算,然后通过与运算计算数组索引(index = hash & (length-1))。
    • 查找桶下包含目标键的位置,完成后返回值。

    LinkedHashMap

    LinkedHashMap基于数组+双向链表+红黑树的结构,主要特点:

  • 继承自HashMap,只改动了一部分方法。
  • 双向链表维护顺序,支持双向遍历。
  • 元素稀疏化地分布在各个桶中,查询效率与HashMap相同。
  • fail-fast原理

    保护模式机制

  • modCount机制: 用于检测集合是否被修改。
  • CheckForComodification过程: 在迭代等操作中,比较modCount和expectedModCount,如果不一致,抛出ConcurrentModificationException。
  • 解决方案: 使用CopyOnWriteArrayList,通过每次操作生成新的数组副本,不影响正在使用的迭代器。
  • CopyOnWriteArrayList

    • 实现原理: 在每次写操作时,副本数组上进行修改,与原始数组相互不影响。
    • 优点: 无需额外判断modCount,因数组为volatile类型,迭代器获取的数组版本保持一致。

    问答

  • 为什么LinkedList插入和删除快

    因为其基于双向链表,插入时只需调整邻接关系,无需移动数组元素。

  • 为什么ArrayList随机访问快

    ArrayList基于数组,直接访问索引位置即可,无需遍历链表。

  • 为什么CopyOnWriteArrayList无需modCount判断

    由于数组为volatile类型,保证内存缓存一致性,允许不判断modCount。


  • Map内部存储逻辑

    数据存储方式

  • 数组储存桶:满载因子0.75时,触发扩容。
  • 链表与红黑树:同一桶中键值对数量超过一定阈值时,改用红黑树以加快查询速度。
  • 存储状态:链表存储较少节点,提升查询效率。
  • 查找逻辑

  • 计算索引:通过hash值与运算,计算放置位置。
  • 验证位置:确定了桶后,遍历链表或红黑树,找出对应键的位置。
  • 返回值:找到对应键值对后,直接返回。
  • 扩容机制

    • 初始容量为16,后续扩容至32、64等。
    • 每次扩容复制现有数组的所有内容。
    • 改进版本从16直接扩至32,减少重新计算 hash 的次数。

    总结

    • List选择建议:根据具体场景选择ArrayList或LinkedList,结合线程安全要求选择Vector或CopyOnWriteArrayList。
    • Map实现细节:了解HashMap的链表遍历与红黑树替换机制,合理选择内存布局,优化查询性能。

    通过以上解析,可以更好地理解List和Map的实现特点及其应用场景,为日常开发提供有力支持。

    上一篇:重定向(response)与转发(request)
    下一篇:idea maven环境隔离

    发表评论

    最新留言

    不错!
    [***.144.177.141]2025年04月25日 21时37分24秒