Java 集合是业务开发中使用频率最高的基础库之一,也是 Java 面试最常考的模块。学习集合时,既要知道每个容器适合什么场景,也要理解扩容、哈希冲突、迭代器、线程安全和并发容器背后的设计取舍。
适合谁看
- 想系统掌握 Java 集合框架的后端开发者。
- 准备 List、Map、Queue、并发集合和源码分析相关面试题的同学。
- 平时经常使用集合,但对扩容、哈希冲突、fail-fast、线程安全等细节不熟的读者。
- 想阅读 JDK 源码,从常用集合类开始建立源码分析能力的工程师。
Java 集合是业务开发中使用频率最高的基础库之一,也是 Java 面试最常考的模块。学习集合时,既要知道每个容器适合什么场景,也要理解扩容、哈希冲突、迭代器、线程安全和并发容器背后的设计取舍。
LinkedHashMap 是 Java 提供的一个集合类,它继承自 HashMap,并在 HashMap 基础上维护一条双向链表,使得具备如下特性:
DelayQueue 是 JUC 包(java.util.concurrent)为我们提供的延迟队列,用于实现延时任务比如订单下单 15 分钟未支付直接取消。它是 BlockingQueue 的一种,底层是一个基于 PriorityQueue 实现的一个无界队列,是线程安全的。关于PriorityQueue可以参考笔者编写的这篇文章:PriorityQueue 源码分析 。
Java 阻塞队列的历史可以追溯到 JDK1.5 版本,当时 Java 平台增加了 java.util.concurrent,即我们常说的 JUC 包,其中包含了各种并发流程控制工具、并发容器、原子类等。这其中自然也包含了我们这篇文章所讨论的阻塞队列。
为了解决高并发场景下多线程之间数据共享的问题,JDK1.5 版本中出现了 ArrayBlockingQueue 和 LinkedBlockingQueue,它们是带有生产者-消费者模式实现的并发容器。其中,ArrayBlockingQueue 是有界队列,即添加的元素达到上限之后,再次添加就会被阻塞或者抛出异常。而 LinkedBlockingQueue 则由链表构成的队列,正是因为链表的特性,所以 LinkedBlockingQueue 在添加元素上并不会向 ArrayBlockingQueue 那样有着较多的约束,所以 LinkedBlockingQueue 设置队列是否有界是可选的(注意这里的无界并不是指可以添加任意数量的元素,而是说队列的大小默认为 Integer.MAX_VALUE,近乎于无限大)。
在 JDK1.5 之前,如果想要使用并发安全的 List 只能选择 Vector。而 Vector 是一种老旧的集合,已经被淘汰。Vector 对于增删改查等方法基本都加了 synchronized,这种方式虽然能够保证同步,但这相当于对整个 Vector 加上了一把大锁,使得每个方法执行的时候都要去获得锁,导致性能非常低下。
JDK1.5 引入了 Java.util.concurrent(JUC)包,其中提供了很多线程安全且并发性能良好的容器,其中唯一的线程安全 List 实现就是 CopyOnWriteArrayList 。关于java.util.concurrent 包下常见并发容器的总结,可以看我写的这篇文章:Java 常见并发容器总结 。
LinkedList 是一个基于双向链表实现的集合类,经常被拿来和 ArrayList 做比较。关于 LinkedList 和ArrayList的详细对比,我们 Java 集合常见面试题总结(上)有详细介绍到。
PriorityQueue 源码分析 为我的知识星球(点击链接即可查看详细介绍以及加入方法)专属内容,已经整理到了《Java 必读源码系列》中。
Java 集合,也叫作容器,主要是由两大接口派生而来:一个是 Collection接口,主要用于存放单一元素;另一个是 Map 接口,主要用于存放键值对。对于Collection 接口,下面又有三个主要的子接口:List、Set 、 Queue。
Java 集合框架如下图所示:
这篇文章我根据《阿里巴巴 Java 开发手册》总结了关于集合使用常见的注意事项以及其具体原理。
强烈建议小伙伴们多多阅读几遍,避免自己写代码的时候出现这些低级的问题。
《阿里巴巴 Java 开发手册》的描述如下:
判断所有集合内部的元素是否为空,使用
isEmpty()方法,而不是size()==0的方式。
这是因为 isEmpty() 方法的可读性更好,并且时间复杂度为 O(1)。
本文来自末读代码投稿:https://mp.weixin.qq.com/s/AHWzboztt53ZfFZmsSnMSw ,JavaGuide 对原文进行了大篇幅改进优化。
上一篇文章介绍了 HashMap 源码,反响不错,也有很多同学发表了自己的观点,这次又来了,这次是 ConcurrentHashMap 了,作为线程安全的 HashMap ,它的使用频率也是很高。那么它的存储结构和实现原理是怎么样的呢?