理解Java集合的基本用法—Collection:List、Set 和 Queue,Map
本博文部分参考 博客 ,强烈推荐这篇博客,写得超级全面!!!

图片来源
Java 集合框架
主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合(单列集合);另一种是 Map ,存储键/值对映射。
Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类。
-
Collection:所有单列集合的根接口。
-
List:有序、允许重复元素的集合。
-
Set:无序、不允许重复元素的集合。
-
Queue:用于存储按特定顺序处理的元素(如先进先出 FIFO)。
-
-
Map:映射接口(双列接口),用于存储键值对(Key-Value),提供对键值的快速查找。

图片来源
由于Java的集合设计非常久远,中间经历过大规模改进,我们要注意到有一小部分集合类是遗留类,不应该继续使用:
- Hashtable:一种线程安全的Map实现;
- Vector:一种线程安全的List实现;
- Stack:基于Vector实现的LIFO的栈。
还有一小部分接口是遗留接口,也不应该继续使用:
- Enumeration:已被Iterator取代。
List(有序集合,允许重复元素)
List 是一个有序的集合,元素按插入顺序排列,允许重复元素。
实现类:
- ArrayList 基于动态数组实现,支持随机访问和快速查找,但插入和删除操作的性能较差,尤其是在中间位置操作时。
- LinkedList 基于双向链表实现,插入和删除操作效率较高,适合频繁的插入和删除,但随机访问的性能差。
- Vector(ArrayList是非线程安全的,效率高;Vector是基于线程安全的 List 实现,效率低 ,遗留类,通常不推荐使用) 。
ArrayList 是最常用的 List 实现类。
List<String> list = new ArrayList<>();
常用方法:
- boolean add(E element):在末尾添加一个元素。
- boolean add(int index, E element):在指定索引添加一个元素。
- E get(int index):获取指定索引的元素。
- E set(int index, E element):设置指定位置的元素,返回先前在 index 处出现的元素。
- boolean remove(Object o):删除指定元素。
- E remove(int index):删除指定索引的元素。
- int size():获取集合大小。
- boolean contains(Object o):判断是否包含某元素。
- int indexOf(Object o):可以返回某个元素的索引,如果元素不存在,就返回-1。
我们来比较一下 ArrayList 和 LinkedList :
| ArrayList | LinkedList | |
|---|---|---|
| 获取指定元素 | 速度很快 | 需要从头开始查找元素 |
| 添加元素到末尾 | 速度很快 | 速度很快 |
| 在指定位置添加/删除 | 需要移动元素 | 不需要移动元素 |
| 内存占用 | 少 | 较大 |
通常情况下,我们总是优先使用 ArrayList。
另外,我们要始终坚持使用迭代器 Iterator 来访问 List ,因为总是具有最高的访问效率。
public class Main {public static void main(String[] args) {List<String> list = List.of("apple", "pear", "banana");for (Iterator<String> it = list.iterator(); it.hasNext(); ) {String s = it.next();System.out.println(s);}}
}
Java 的 for each 循环本身可以帮我们使用 Iterator 遍历。可以把上面的代码改写成:
ublic class Main {public static void main(String[] args) {List<String> list = List.of("apple", "pear", "banana");for (String s : list) {System.out.println(s);}}
}
List 可以和 Array 相互转换:
把 List 变为 Array 有三种方法:
- 调用toArray()方法直接返回一个Object[]数组,这种方法会丢失类型信息,所以实际应用很少。
List<String> list = List.of("apple", "pear", "banana"); // 如果我们调用List.of(),它返回的是一个只读List
Object[] array = list.toArray();
- 给 toArray(T[]) 传入一个类型相同的 Array,List 内部自动把元素复制到传入的 Array 中。
List<Integer> list = List.of(12, 34, 56); //如果我们调用List.of(),它返回的是一个只读List
Integer[] array = list.toArray(new Integer[list.size()]);
- 通过List接口定义的T[] toArray(IntFunction<T[]> generator)方法。
Integer[] array = list.toArray(Integer[]::new);
把 Array 变为 List,通过 List.of(T…) 方法最简单:
Integer[] array = { 1, 2, 3 };
List<Integer> list = List.of(array);
总结
-
List 是按索引顺序访问的长度可变的有序表,优先使用 ArrayList 而不是 LinkedList;
-
可以直接使用 for each 遍历 List;
-
List 可以和 Array 相互转换。
Set(无序集合,不允许重复元素)
Set 是一个不允许重复元素的集合,它不保证元素的顺序。Set 实际上相当于只存储 key、不存储 value 的 Map。我们经常用 Set 用于去除重复元素。
Set 接口并不保证有序,而 SortedSet 接口则保证元素是有序的。PS:注意输出的顺序既不是添加的顺序,也不是 String 或 Integer 排序的顺序,在不同版本的JDK中,这个顺序也可能是不同的。
实现类:
- HashSet 基于哈希表实现,元素无序,性能较好,适合用于查找。它实现了Set接口,并没有实现SortedSet接口;
- LinkedHashSet 基于哈希表和链表实现,元素有序(按插入顺序)。
- TreeSet 基于红黑树实现,元素按自然顺序(或提供的 Comparator)排序。它实现了SortedSet接口。
HashSet 是 Set 接口最常用的实现
Set<String> set = new HashSet<>();
常用方法:
- boolean add(E e):添加元素。
- boolean remove(Object o):删除指定元素。
- boolean contains(Object o):判断是否包含某元素。
- int size():获取集合大小。
- clear():清空集合。
Queue / Deque
Queue 是一个先进先出(FIFO:First In First Out)的集合,只能一头进,另一头出。
实现类:
-
PriorityQueue:基于优先级堆实现,支持优先级排序的队列。PriorityQueue 并不是一个比较标准的队列实现,PriorityQueue 保存队列元素的顺序并不是按照加入队列的顺序,而是按照队列元素的大小进行重新排序。
-
Deque:Queue 是队列,只能一头进,另一头出。双端队列 Deque(Double Ended Queue)允许两头都进,两头都出。
-
ArrayDeque:基于数组实现,作为栈或队列使用,效率较高。
-
LinkedList:实现了 Queue 接口,适合用于队列操作。
-
Queue<String> queue = new LinkedList<>();
Queue
常用方法:
- boolean add(E) / boolean offer(E):添加元素到队尾;
- E remove() / E poll():获取队首元素并从队列中删除;
- E element() / E peek():获取队首元素但并不从队列中删除。
- int size():获取队列大小。
对于具体的实现类,有的Queue有最大队列长度限制,有的Queue没有。注意到添加、删除和获取队列元素总是有两个方法,这是因为在添加或获取元素失败时,这两个方法的行为是不同的:
| throw Exception | 返回false或null | |
|---|---|---|
| 添加元素到队尾 | add(E e) | boolean offer(E e) |
| 取队首元素并删除 | E remove() | E poll() |
| 取队首元素但不删除 | E element() | E peek() |
注意:不要把 null 添加到队列中,否则 poll() 方法返回 null 时,很难确定是取到了 null 元素还是队列为空。
Deque
Deque 接口继承自 Queue 接口
Queue 和 Deque 出队和入队的方法比较:
| Queue | Deque | |
|---|---|---|
| 添加元素到队尾 | add(E e) / offer(E e) | addLast(E e) / offerLast(E e) |
| 取队首元素并删除 | E remove() / E poll() | E removeFirst() / E pollFirst() |
| 取队首元素但不删除 | E element() / E peek() | E getFirst() / E peekFirst() |
| 添加元素到队首 | 无 | addFirst(E e) / offerFirst(E e) |
| 取队尾元素并删除 | 无 | E removeLast() / E pollLast() |
| 取队尾元素但不删除 | 无 | E getLast() / E peekLast() |
Deque 接口实际上扩展自 Queue,因此,Queue 提供的 add()/offer() 方法在 Deque 中也可以使用,但是,使用 Deque,最好不要调用offer(),而是调用 offerLast()。即使用 Deque,推荐总是明确调用 offerLast() / offerFirst() 或者 pollFirst() / pollLast() 方法。
Deque 是一个接口,它的实现类有 ArrayDeque 和 LinkedList。
LinkedList,它即是List,又是Queue,还是Deque。但是我们在使用的时候,总是用特定的接口来引用它,这是因为持有接口说明代码的抽象层次更高,而且接口本身定义的方法代表了特定的用途。
// 不推荐的写法:
LinkedList<String> d1 = new LinkedList<>();// 推荐的写法:
Deque<String> d2 = new LinkedList<>();
可见面向抽象编程的一个原则就是:尽量持有接口,而不是具体的实现类。
总结
Deque实现了一个双端队列(Double Ended Queue),它可以:
-
将元素添加到队尾或队首:addLast()/offerLast()/addFirst()/offerFirst();
-
从队首/队尾获取元素并删除:removeFirst()/pollFirst()/removeLast()/pollLast();
-
从队首/队尾获取元素但不删除:getFirst()/peekFirst()/getLast()/peekLast();
-
总是调用xxxFirst()/xxxLast()以便与Queue的方法区分开;
-
避免把null添加到队列。
Stack
栈(Stack)是一种后进先出(LIFO:Last In First Out)的数据结构,元素的插入和删除操作都发生在栈的顶端。虽然 Stack 类是 Java 提供的传统类,但它已被 Deque 接口的 ArrayDeque 替代,ArrayDeque 提供了更高效的栈操作。常见实现:Stack(遗留类,较旧,不推荐使用)、ArrayDeque(推荐使用)。
Deque<String> stack = new ArrayDeque<>();
在Java中,我们用 Deque 可以实现 Stack 的功能:
-
把元素压栈:push(E) / addFirst(E);
-
把栈顶的元素“弹出”:pop() / removeFirst();
-
取栈顶元素但不弹出:peek() / peekFirst()。
为什么 Java 的集合类没有单独的 Stack 接口呢?因为有个遗留类名字就叫 Stack,出于兼容性考虑,所以没办法创建 Stack 接口,只能用Deque 接口来“模拟”一个 Stack 了。
当我们把 Deque 作为 Stack 使用时,注意只调用 push() / pop() / peek() 方法,不要调用 addFirst() / removeFirst() / peekFirst() 方法,这样代码更加清晰。
Map(映射,存储键值对)
Map 是一个存储键值对(key-value)的集合,Map 中的键是唯一的,值可以重复。
实现类:
-
HashMap:基于哈希表实现,查找和插入的性能较高,元素无序。(HashMap 非线程安全,高效,支持null)
-
LinkedHashMap:保持插入顺序的 HashMap 实现。
-
TreeMap:基于红黑树实现,元素按键的自然顺序或指定的 Comparator 排序。
-
Hashtable:遗留类,过时的线程安全版本,不推荐使用。(HashTable 线程安全,低效,不支持null )
HashMap 是 Map 接口最常用的实现,基于哈希表实现。它在内部会对 Key 进行排序,这种 Map 就是 SortedMap。注意到 SortedMap 是接口,它的实现类是 TreeMap。
Map<String, String> map = new HashMap<>();
常用方法:
-
put(K key, V value):添加键值对。
-
get(Object key):根据键获取对应的值。
-
remove(Object key):删除指定键的键值对。
-
boolean containsKey(Object key):判断是否包含指定键。
-
containsValue(Object value):判断是否包含指定值。
-
keySet():获取所有键。
-
values():获取所有值。
PS: Map 中不存在重复的 key,因为放入相同的 key ,只会把原有的 key-value 对应的 value 给替换掉。
遍历 Map (无序,既不是插入顺序,也不是某个逻辑下的排序顺序)
for (String key : map.keySet()) { // keySet()方法返回的Set集合,它包含不重复的key的集合Integer value = map.get(key);System.out.println(key + " = " + value);}for (Map.Entry<String, Integer> entry : map.entrySet()) { // entrySet()集合,它包含每一个key-value映射String key = entry.getKey();Integer value = entry.getValue();System.out.println(key + " = " + value);
}相关文章:
理解Java集合的基本用法—Collection:List、Set 和 Queue,Map
本博文部分参考 博客 ,强烈推荐这篇博客,写得超级全面!!! 图片来源 Java 集合框架 主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合(单列…...
IOC容器实现分层解耦
文章开始之前,先引入软件开发的两个名词:耦合和内聚。耦合是指:衡量软件中各个层(三层架构)/各个模块的依赖关联程度;内聚是指:软件中各个功能模块内部的功能联系。三层架构中Controller、Servi…...
Flutter 共性元素动画
在 Flutter 中,共性元素动画(Shared Element Transitions)用于在页面导航或组件切换时创建视觉上更流畅和连贯的动画效果。这种动画可以使用户感受到两个界面之间的“物理联系”,比如图片从缩略图到全屏的扩大效果。 前置知识点整…...
K8s内存溢出问题剖析:排查与解决方案
文章目录 一、背景二、排查方案:1. 可能是数据量超出了限制的大小,检查数据目录大小2. 查看是否是内存溢出2.1 排查数据量(查看数据目录大小是否超过limit限制)2.2 查看pod详情发现问题 三、解决过程 一、背景 做redis压测过程中…...
乌班图单机(不访问外网)部署docker和服务的方法
面向对象:Ubuntu不能访问外网的机子,部署mysql、redis、jdk8、minio 过程: 1、安装docker(照着图去这里找对应的下载下来https://download.docker.com/linux/static/stable/),将7个docker官网下载的文件下载下来后,传上去服务器随便一个文件夹或者常用的opt或者/usr/lo…...
使用 pycharm 新建使用 conda 虚拟 python 环境的工程
1. conda 常见命令复习: conda env list // 查看 conda 环境列表 conda activate xxxenv // 进入指定 conda 环境2. 环境展示: 2.1. 我的物理环境的 Python 版本为 3.10.9: 2.2. 我的 conda 虚拟环境 env_yolov9_python_3_8 中的 pyth…...
Docker的save和export命令的区别,load和import的区别 笔记241124
Docker的save和export命令的区别,load和import的区别 解说1: Docker的save和export命令,以及load和import命令,在功能和使用场景上存在显著的区别。以下是对这两组命令的详细对比和解释: Docker save和export命令的区别 使用方式和目的&am…...
通俗理解人工智能、机器学习和深度学习的关系
最近几年人工智能成为极其热门的概念和话题,可以说彻底出圈了。但人工智能的概念在1955年就提出来了,可以说非常古老。我在上小学的时候《科学》课本上就有人工智能的概念介绍,至今还有印象,但那些年AI正处于“寒冬”,…...
使用 pycharm 新建不使用 python 虚拟环境( venv、conda )的工程
有时候我们发现一个好玩的 demo,想赶快在电脑上 pip install 一下跑起来,发现因为 python 的 venv、conda 环境还挺费劲的,因为随着时间的发展,之前记得很清楚的 venv、conda 的用法,不经常使用,半天跑不起…...
【大数据学习 | Spark-SQL】SparkSQL读写数据
我们使用sparksql进行编程,编程的过程我们需要创建dataframe对象,这个对象的创建方式我们是先创建RDD然后再转换rdd变成为DataFrame对象。 但是sparksql给大家提供了多种便捷读取数据的方式。 //原始读取数据方式 sc.textFile().toRDD sqlSc.createDat…...
AI赋能公共服务转型升级 | 第十届中国行业互联网大会暨腾讯云TVP行业大使三周年庆典公共服务专场圆满举办!
引言 党的二十大报告把“基本公共服务实现均等化”作为 2035 年我国发展的总体目标之一,强调要“健全基本公共服务体系,提高公共服务水平”。AI 作为新质生产力的核心驱动力之一,正在公共服务领域发挥着越来越重要的作用。 2024 年 10 月 2…...
关于按天切割Tomcat的catalina.out日志文件的配置
1、catalina.out 是 Tomcat 的标准输出和标准错误日志,通常输出到 Tomcat 安装目录下的 logs 文件夹中。这个日志文件会记录 Tomcat 启动、停止以及运行过程中产生的所有日志信息。 2、在Apache Tomcat中,日志文件catalina.out默认情况下不会自动按天切割…...
【人工智能】深入解析GPT、BERT与Transformer模型|从原理到应用的完整教程
在当今人工智能迅猛发展的时代,自然语言处理(NLP)领域涌现出许多强大的模型,其中GPT、BERT与Transformer无疑是最受关注的三大巨头。这些模型不仅在学术界引起了广泛讨论,也在工业界得到了广泛应用。那么,G…...
彻底理解如何保证ElasticSearch和数据库数据一致性问题
一.业务场景举例 需求: 一个卖房业务,双十一前一天,维护楼盘的运营人员突然接到合作开发商的通知,需要上线一批热门的楼盘列表,上传完成后,C端小程序支持按楼盘的名称、户型、面积等产品属性全模糊搜索热门…...
2024-2025热门留学趋势
在信息爆炸的时代,留学已成为许多人规划未来、拓宽视野的重要途径。随着全球教育格局的不断变化,留学领域也涌现出一系列新热点和趋势。本文将为您解读2024年最热门的留学话题,并提供实用的准备策略,助您在留学之路上一帆风顺。 热…...
寻找视频特效素材的优质网站推荐 轻松提升作品魅力
在短视频、影视和广告制作中,视频特效素材已成为提升作品专业感的关键元素。炫酷的光效、震撼的爆炸、动感的粒子效果和流畅的转场特效,都能让作品更具吸引力。那么,视频特效素材去哪里找呢?今天,小编为大家精心挑选了…...
【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-36
文件下载与邀请翻译者 学习英特尔开发手册,最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册,会是一件耗时费力的工作。如果有愿意和我一起来做这件事的,那么ÿ…...
信息安全实验--密码学实验工具:CrypTool
1. CrypTool介绍💭 CrypTool 1的开源教育工具,用于密码学研究。通过CrypTool 1,可以实现加密和解密操作,数字签名。CrypTool1和2有很多区别的。 2. CrpyTool下载🔧 在做信息安全实验--密码学相关实验时,发…...
python的class 类创建、方法调用以及属性赋值
题目:购物车系统 创建一个简单的购物车系统,要求如下: 定义一个 Product 类,表示商品,包含以下属性和方法: 属性: name:商品名称(字符串) price࿱…...
Angular v19 (二):响应式当红实现signal的详细介绍:它擅长做什么、不能做什么?以及与vue、svelte、react等框架的响应式实现对比
本文紧接着Angular v19 新版本来啦,一起瞧瞧新特性吧!,主要针对它在v18引入了一项全新的响应式技术——Signal,这引起了开发者社区的广泛关注,最新的v19版本推出了更多的signal工具。Signal的加入旨在优化Angular的响应…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
