Java 集合框架总览

总览图

以下是 Java 集合框架的uml类图: alt

实现类介绍

以下是 Java 集合框架中一些常见实现类的特点和实现原理:

1. ArrayList

  • 特点
    • 动态数组:它是基于动态数组实现的,支持随机访问,通过索引可以快速定位元素,时间复杂度为
    • 可扩容:当数组空间不足时,会自动进行扩容操作,一般是扩容为原来容量的 1.5 倍。
    • 有序性:元素按照插入顺序排列。
    • 允许重复元素和 null
  • 实现原理
    • 内部维护一个 Object 类型的数组,当添加元素时,如果数组容量不足,会创建一个新的更大的数组,并将原数组中的元素复制到新数组中。
    • 随机访问时,直接根据索引访问数组对应位置的元素。

2. LinkedList

  • 特点
    • 双向链表:基于双向链表实现,插入和删除操作效率较高,特别是在链表头部和尾部进行操作,时间复杂度为
    • 不支持随机访问:随机访问元素时,需要从头或尾开始遍历链表,时间复杂度为
    • 有序性:元素按照插入顺序排列。
    • 允许重复元素和 null
  • 实现原理
    • 内部维护了一个双向链表,每个节点包含数据、指向前一个节点的引用和指向后一个节点的引用。
    • 插入和删除操作只需要修改相邻节点的引用关系。

3. Vector

  • 特点
    • 动态数组:和 ArrayList 类似,也是基于动态数组实现的。
    • 线程安全:它的大部分方法都使用了 synchronized 关键字进行同步,保证在多线程环境下的线程安全,但这也导致了性能开销较大。
    • 可扩容:当数组空间不足时,会自动进行扩容操作,默认扩容为原来容量的 2 倍。
    • 有序性:元素按照插入顺序排列。
    • 允许重复元素和 null
  • 实现原理
    • 内部维护一个 Object 类型的数组,和 ArrayList 扩容机制类似,但扩容倍数不同。
    • 方法使用 synchronized 进行同步,保证线程安全。

4. Stack

  • 特点
    • 后进先出(LIFO):继承自 Vector,遵循后进先出的原则,支持 push(入栈)、pop(出栈)、peek(查看栈顶元素)等操作。
    • 线程安全:由于继承自 Vector,所以也是线程安全的。
  • 实现原理
    • 基于 Vector 实现,通过调用 Vector 的方法来实现栈的操作,例如 push 方法调用 addElement 方法,pop 方法调用 removeElementAt 方法。

5. HashSet

  • 特点
    • 无序性:不保证元素的插入顺序,元素的存储顺序是由哈希值决定的。
    • 唯一性:不允许存储重复元素,通过元素的 hashCode()equals() 方法来判断元素是否重复。
    • 允许 null:但只能有一个 null 值。
  • 实现原理
    • 内部基于 HashMap 实现,HashSet 中的元素实际上是存储在 HashMap 的键中,HashMap 的值统一为一个静态的 Object 对象。
    • 插入元素时,先计算元素的哈希值,根据哈希值找到对应的桶位置,如果桶为空,则直接插入;如果桶不为空,则通过 equals() 方法比较元素是否重复,不重复则插入。

6. TreeSet

  • 特点
    • 有序性:根据元素的自然顺序或指定的比较器进行排序,元素会按照排序后的顺序存储。
    • 唯一性:不允许存储重复元素,通过元素的比较结果来判断元素是否重复。
    • 不允许 null:因为需要对元素进行比较排序。
  • 实现原理
    • 内部基于 TreeMap 实现,TreeSet 中的元素实际上是存储在 TreeMap 的键中,TreeMap 的值统一为一个静态的 Object 对象。
    • TreeMap 基于红黑树实现,插入元素时,会根据元素的比较结果将元素插入到红黑树的合适位置,保证树的平衡和有序性。

7. LinkedHashSet

  • 特点
    • 有序性:保证元素的插入顺序,即元素按照插入的先后顺序存储。
    • 唯一性:不允许存储重复元素,通过元素的 hashCode()equals() 方法来判断元素是否重复。
    • 允许 null:但只能有一个 null 值。
  • 实现原理
    • 内部基于 LinkedHashMap 实现,LinkedHashSet 中的元素实际上是存储在 LinkedHashMap 的键中,LinkedHashMap 的值统一为一个静态的 Object 对象。
    • LinkedHashMap 维护了一个双向链表,用于记录元素的插入顺序。

8. HashMap

  • 特点
    • 键值对存储:以键值对(key - value)的形式存储数据,每个键是唯一的。
    • 无序性:不保证元素的插入顺序,元素的存储顺序是由键的哈希值决定的。
    • 允许 null 键和 null:但 null 键只能有一个。
  • 实现原理
    • 内部基于哈希表实现,哈希表是一个数组,数组的每个元素是一个链表或红黑树(当链表长度超过 8 且数组长度大于 64 时,链表会转换为红黑树)。
    • 插入元素时,先计算键的哈希值,根据哈希值找到对应的桶位置,如果桶为空,则直接插入;如果桶不为空,则遍历链表或红黑树,通过 equals() 方法比较键是否重复,不重复则插入。

9. TreeMap

  • 特点
    • 键值对存储:以键值对(key - value)的形式存储数据,每个键是唯一的。
    • 有序性:根据键的自然顺序或指定的比较器进行排序,键会按照排序后的顺序存储。
    • 不允许 null:因为需要对键进行比较排序。
  • 实现原理
    • 内部基于红黑树实现,红黑树是一种自平衡的二叉搜索树。
    • 插入元素时,根据键的比较结果将元素插入到红黑树的合适位置,保证树的平衡和有序性。

10. LinkedHashMap

  • 特点
    • 键值对存储:以键值对(key - value)的形式存储数据,每个键是唯一的。
    • 有序性:可以保持插入顺序或访问顺序,当 accessOrderfalse 时,按照插入顺序;为 true 时,按照访问顺序(每次访问元素后,该元素会被移动到链表尾部)。
    • 允许 null 键和 null:但 null 键只能有一个。
  • 实现原理
    • 内部基于哈希表和双向链表实现,哈希表用于快速查找键值对,双向链表用于记录元素的顺序。
    • 插入元素时,先计算键的哈希值,根据哈希值找到对应的桶位置,如果桶为空,则直接插入;如果桶不为空,则遍历链表或红黑树,通过 equals() 方法比较键是否重复,不重复则插入,并更新双向链表的顺序。

11. Hashtable

  • 特点
    • 键值对存储:以键值对(key - value)的形式存储数据,每个键是唯一的。
    • 线程安全:它的大部分方法都使用了 synchronized 关键字进行同步,保证在多线程环境下的线程安全,但这也导致了性能开销较大。
    • 不允许 null 键和 null
  • 实现原理
    • 内部基于哈希表实现,和 HashMap 类似,但方法使用 synchronized 进行同步,保证线程安全。

12. WeakHashMap

  • 特点
    • 键值对存储:以键值对(key - value)的形式存储数据,每个键是唯一的。
    • 弱引用键:键是使用弱引用存储的,当键所引用的对象被垃圾回收时,对应的键值对会自动从 WeakHashMap 中移除。
    • 允许 null 键和 null:但 null 键只能有一个。
  • 实现原理
    • 内部基于哈希表实现,键使用 WeakReference 进行包装,当键所引用的对象被垃圾回收时,WeakReference 会被加入到引用队列中,WeakHashMap 会定期检查引用队列,将对应的键值对从哈希表中移除。

13. Properties

  • 特点
    • 键值对存储:继承自 Hashtable,以键值对(key - value)的形式存储数据,键和值都是 String 类型。
    • 常用于配置文件:可以方便地从文件中加载配置信息,也可以将配置信息保存到文件中。
  • 实现原理
    • 基于 Hashtable 实现,提供了一些方便的方法来处理 String 类型的键和值,例如 load 方法用于从文件中加载配置信息,store 方法用于将配置信息保存到文件中。
Java集合框架 文章被收录于专栏

Java集合框架是Java提供的一组用于存储和操作数据的类和接口,它位于java.util包中,为开发者提供了强大且灵活的数据存储和处理能力。以下将从整体架构、主要接口、常用实现类、使用场景以及示例代码等方面详细介绍Java集合框架。

全部评论
点赞 回复 分享
发布于 03-30 18:00 北京

相关推荐

250228 一面 25min介绍Java 里面常用的集合?ArrayList 和 LinkedList,它们两个的使用场景是什么?HashMap里面插入一个元素的过程?Hashmap把同一个元素 put 两次,会有几个?是怎么比较的?==和equals的区别?创建一个线程池的几个参数?拒绝策略的代码是由哪个线程去执行的?队列如果我们给它设置成无界队列,这个会对我们的服务会有什么影响?实习项目的消息队列为什么最终选择了 Kafka 这个实现?项目:netty里面的线程模型?bossgroup 里面它是有几个线程,这个了解吗?介绍一下spring 的AOP?AOP的实现原理是什么?Java的动态代理了解吗?这个动态代理和 AOP 有关系吗?没有实现接口,如何使用动态代理?思考一下,JDK动态代理和CGlib动态代理,它们在性能上有什么差别,从创建和调用两个方面讲?synchronize是在什么公共资源上面加锁?创建一个 Java 对象,除了包含值,还有什么部分?那一般我们传入一个对象的时候,synchronize 它这个数据它是存在对象的哪里的?手撕:分割链表 ********************************************************************* 二面 50min 线下面实习拷打。一个普通的微服务都需要哪些模块或者组件?这里面哪一块你比较熟吗?网关服务提供哪些能力?    项目拷打。通讯协议怎么实现的?传输的内容里面如果也有魔数怎么办?那你弄这个通讯协议有啥好的效果吗?这个项目有什么收获没有?学习哪些原理啊?一个好的 RPC 通讯协议需要具备哪些特点?内网用需要考虑安全性吗?为什么要用编解码?RPC还有其他的那个好处吗,为什么需要RPC?你觉得你回答的好吗?    企业让你去做一个订单查询的一个接口的话,这么一个需求的话,你觉得大概率都需要去了解哪方面都行,这使用哪方面的技能或者功能?在美团的时候用过刚才说的这些吗?修改锁的这个过程应该是什么样的?乐观锁和悲观锁的区别是啥?update语句在mysql里面执行过程是什么样的?你是真知道还是只是在猜测?    比如说你的同学,或者说你同级的这些人这么多,你比他们有优势吗?感觉你的这些别人也都可以做?为什么你现在没有实习?    Netty的NIO是什么样的?BIO的线程阻塞为什么还会占用cpu呢?什么情况下比较适合用多路复用?    实习的话能实习多久?全职是吧?你同学在哪里实习?你为什么没有去选算法方面的实习?有没有想过开发的其实业务需求压力会大一些?比如说我们这很多事情都要求你加班加点到很晚?    相对于别人,你的这个实习经历确实有点少。来我们这的话很多东西都得现学。你是哪里人?    反问后续安排    加问。你们最近用 AI 吗?那个 prompt 有什么经验吗?怎么样能让这个结果更好?    场景题。一个文件里有几十亿个id,类型可能是id,也可能是时间戳,数量未知,随机抽取 5, 000 条
点赞 评论 收藏
分享
03-16 21:51
河北大学 后端
结束后20分组约二面1. 自我介绍2. 专业都学了什么相关课程?3. 说一下你觉得 SpringBoot 是干什么的4. 如何使用springboot搭建一个程序?5. mapper service controller是springboot的吗?6. 为什么要拆成这三层?为什么是三层?7. 除了三层架构还有别的架构吗?8. 介绍mybatisPlus?9. 如果用mybatis查询需要写哪些文件?(xml或mapper层接口)10. 写在接口里的,没有实现类,该怎么调用?11. websocket在项目里是干什么的?12. websocket和http的区别?13. 写多线程代码,通过输出内容可以看出是多线程运行的。(写了一个出现并发问题的代码)14. 如何解决这个多线程问题?(加锁)15. reentranktlock相比另一个锁,为什么更灵活?(trylock,公平锁)16. 什么是公平锁?17. 从你学过的课程里面,你觉得如果要实现一个锁,最关键的是什么?(答保证操作的原子性)18. 原子性是什么?19. 获取锁的过程需要几步?(答要获取到锁,把互斥变量改为1)20. 什么叫获取到锁?(答用cas操作记录下获取锁的线程)21. 什么是cas?是干什么的?22. 结合上面这么一条链路,你觉得实现一个锁最关键步骤是哪个步骤?(答cas)23. java能实现多进程吗?24. 线程和进程的区别?25. 你刚刚说的,启动qq会启动一个进程吗?手撕1. 链表里倒数第k个元素(一次遍历)跟面试官说上午刚写过这个,讨论实现方式和时空复杂度2. 把数组转化成二叉树3. sql,先设计表再写sql(sql太不熟练了,才写了一般面试官说时间到了就没接着写,中间还问了关系表的“关系”是什么,数据库三范式)#牛客AI配图神器#
LYeT:感觉上来就问的比较偏?看牛客字节面经都不怎么问spring的,就一点也没准备,上来就红温
查看28道真题和解析
点赞 评论 收藏
分享
评论
1
2
分享

创作者周榜

更多
牛客网
牛客企业服务