Java之Java基础二十(集合[上])

Java 集合框架可以分为两条大的支线:
①、Collection,主要由 List、Set、Queue 组成:
- List 代表有序、可重复的集合,典型代表就是封装了动态数组的 ArrayList 和封装了链表的 LinkedList;
- Set 代表无序、不可重复的集合,典型代表就是 HashSet 和 TreeSet;
- Queue 代表队列,典型代表就是双端队列 ArrayDeque,以及优先级队列 PriorityQueue。
②、Map,代表键值对的集合,典型代表就是HashMap
一、List
List 的特点是存取有序,可以存放重复的元素,可以用下标对元素进行操作。
(1)ArrayList
先来一段 ArrayList 的增删改查,学会用。
// 创建一个集合
ArrayList<String> list = new ArrayList<String>();
// 添加元素
list. Add("aa");
list. Add("bb");
list. Add("ccc");// 遍历集合 for 循环
for (int i = 0; i < list.size(); i++) {String s = list. Get(i);System.out.println(s);
}
// 遍历集合 for each
for (String s : list) {System.out.println(s);
}// 删除元素
list.remove(1);
// 遍历集合
for (String s : list) {System.out.println(s);
}// 修改元素
list. Set(1, "aaa");
// 遍历集合
for (String s : list) {System.out.println(s);
}
简单介绍一下 ArrayList 的特征
- ArrayList 是由数组实现的,支持随机存取,也就是可以通过下标直接存取元素;
- 从尾部插入和删除元素会比较快捷,从中间插入和删除元素会比较低效,因为涉及到数组元素的复制和移动;
- 如果内部数组的容量不足时会自动扩容,因此当元素非常庞大的时候,效率会比较低。
(2) LinkedList
同样先来一段 LinkedList 的增删改查,和 ArrayList 几乎没什么差别。
// 创建一个集合
LinkedList<String> list = new LinkedList<String>();
// 添加元素
list. Add("aa");
list. Add("bb");
list. Add("ccc");// 遍历集合 for 循环
for (int i = 0; i < list.size(); i++) {String s = list.get(i);System.out.println(s);
}
// 遍历集合 for each
for (String s : list) {System.out.println(s);
}// 删除元素
list.remove(1);
// 遍历集合
for (String s : list) {System.out.println(s);
}// 修改元素
list. Set(1, "aaa");
// 遍历集合
for (String s : list) {System.out.println(s);
}
不过,LinkedList 和 ArrayList 仍然有较大的不同
- LinkedList 是由双向链表实现的,不支持随机存取,只能从一端开始遍历,直到找到需要的元素后返回;
- 任意位置插入和删除元素都很方便,因为只需要改变前一个节点和后一个节点的引用即可,不像 ArrayList 那样需要复制和移动数组元素;
- 因为每个元素都存储了前一个和后一个节点的引用,所以相对来说,占用的内存空间会比 ArrayList 多一些。
(3) Vector 和 Stack
List 的实现类还有一个 Vector,是一个元老级的类,比 ArrayList 出现得更早。ArrayList 和 Vector 非常相似,只不过 Vector 是线程安全的,像 get、set、add 这些方法都加了 synchronized 关键字,就导致执行效率会比较低,所以现在已经很少用了。
看一下 add 方法的源码
public synchronized boolean add(E e) {elementData[elementCount++] = e;return true;
}
这种加了同步方法的类,注定会被淘汰掉,就像StringBuilder 取代 StringBuffer那样。JDK 源码也说了:
如果不需要线程安全,建议使用 ArrayList 代替 Vector。
Stack 是 Vector 的一个子类,本质上也是由动态数组实现的,只不过还实现了先进后出的功能(在 get、set、add 方法的基础上追加了 pop「返回并移除栈顶的元素」、peek「只返回栈顶元素」等方法),所以叫栈。
下面是这两个方法的源码,增删改查我就不写了,和 ArrayList 和 LinkedList 几乎一样。
public synchronized E pop() {E obj;int len = size();obj = peek();removeElementAt(len - 1);return obj;
}public synchronized E peek() {int len = size();if (len == 0)throw new EmptyStackException();return elementAt(len - 1);
}
不过,由于 Stack 执行效率比较低(方法上同样加了 synchronized 关键字),就被双端队列 ArrayDeque 取代了.
二、Set
Set 的特点是存取无序,不可以存放重复的元素,不可以用下标对元素进行操作,和 List 有很多不同。
(1)HashSet
HashSet 其实是由 HashMap 实现的,只不过值由一个固定的 Object 对象填充,而键用于操作。来简单看一下它的源码。
public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, java.io.Serializable
{private transient HashMap<E,Object> map;// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT = new Object();public HashSet() {map = new HashMap<>();}public boolean add(E e) {return map.put(e, PRESENT)==null;}public boolean remove(Object o) {return map.remove(o)==PRESENT;}
}
实际开发中,HashSet 并不常用,比如,如果我们需要按照顺序存储一组元素,那么 ArrayList 和 LinkedList 可能更适合;如果我们需要存储键值对并根据键进行查找,那么 HashMap 可能更适合。
来一段增删改查体验一下:
// 创建一个新的HashSet
HashSet<String> set = new HashSet<>();// 添加元素
set. Add("aa");
set. Add("bb");
set. Add("ccc");// 输出HashSet的元素个数
System.out.println("HashSet size: " + set.size()); // output: 3// 判断元素是否存在于HashSet中
boolean containsWanger = set. Contains("bb");
System.out.println("Does set contain 'bb'? " + containsWanger); // output: true// 删除元素
boolean removeWanger = set. Remove("bb");
System.out.println("Removed 'bb'? " + removeWanger); // output: true// 修改元素,需要先删除后添加
Boolean removeChenmo = set. Remove("aa");
Boolean addBuChenmo = set. Add("aaa");
System.out.println("Modified set? " + (removeChenmo && addBuChenmo)); // output: true// 输出修改后的HashSet
System.out.println("HashSet after modification: " + set); // output: [ccc, aaa]
HashSet 主要用于去重,比如,我们需要统计一篇文章中有多少个不重复的单词,就可以使用 HashSet 来实现。
// 创建一个 HashSet 对象
HashSet<String> set = new HashSet<>();// 添加元素
set. Add("aa");
set. Add("bb");
set. Add("ccc");
set. Add("aa");// 输出 HashSet 的元素个数
System.out.println("HashSet size: " + set.size()); // output: 3// 遍历 HashSet
for (String s : set) {System.out.println(s);
}
从上面的例子可以看得出,HashSet 会自动去重,因为它是用 HashMap 实现的,HashMap 的键是唯一的(哈希值),相同键的值会覆盖掉原来的值,于是第二次 set.add("沉默") 的时候就覆盖了第一次的 set.add("aa")。
(2)LinkedHashSet
LinkedHashSet 虽然继承自 HashSet,其实是由 LinkedHashMap 实现的。
这是 LinkedHashSet 的无参构造方法:
public LinkedHashSet() {super(16, .75f, true);
}
super 的意思是它将调用父类的 HashSet 的一个有参构造方法:
HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
LinkedHashSet 的增删改查
LinkedHashSet<String> set = new LinkedHashSet<>();// 添加元素
set. Add("aa");
set. Add("bb");
set. Add("ccc");// 删除元素
set. Remove("bb");// 修改元素
set. Remove("aa");
set. Add("aaaaa");// 查找元素
Boolean hasChenQingYang = set. Contains("ccc");
System.out.println("set包含ccc吗?" + hasccc);
在以上代码中,我们首先创建了一个 LinkedHashSet 对象,然后使用 add 方法依次添加了三个元素:aa、bb和ccc。接着,我们使用 remove 方法删除了bb这个元素,并使用 remove 和 add 方法修改了aa这个元素。最后,我们使用 contains 方法查找了ccc这个元素是否存在于 set 中,并打印了结果。
LinkedHashSet 是一种基于哈希表实现的 Set 接口,它继承自 HashSet,并且使用链表维护了元素的插入顺序。因此,它既具有 HashSet 的快速查找、插入和删除操作的优点,又可以维护元素的插入顺序。
(3)TreeSet
与 TreeMap 相似,TreeSet 是一种基于红黑树实现的有序集合,它实现了 SortedSet 接口,可以自动对集合中的元素进行排序。按照键的自然顺序或指定的比较器顺序进行排序。
// 创建一个 TreeSet 对象
TreeSet<String> set = new TreeSet<>();// 添加元素
set. Add("aa");
set. Add("bb");
set. Add("ccc");
System.out.println(set); // 输出 [aa, bb, ccc]// 删除元素
set. Remove("bb");
System.out.println(set); // 输出 [aa, ccc]// 修改元素:TreeSet 中的元素不支持直接修改,需要先删除再添加
set. Remove("ccc");
set. Add("cbc");
System.out.println(set); // 输出 [aa, cbc]// 查找元素
System.out.println(set. Contains("aa")); // 输出 true
System.out.println(set. Contains("bb")); // 输出 false
需要注意的是,TreeSet 不允许插入 null 元素,否则会抛出 NullPointerException 异常。
总体上来说,Set 集合不是关注的重点,因为底层都是由 Map 实现的,为什么要用 Map 实现呢?
因为 Map 的键不允许重复、无序.
参考链接:https://javabetter.cn/collection/gailan.html
相关文章:
Java之Java基础二十(集合[上])
Java 集合框架可以分为两条大的支线: ①、Collection,主要由 List、Set、Queue 组成: List 代表有序、可重复的集合,典型代表就是封装了动态数组的 ArrayList 和封装了链表的 LinkedList;Set 代表无序、不可重复的集…...
【C++BFS】1162. 地图分析
本文涉及知识点 CBFS算法 LeetCode1162. 地图分析 你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距…...
实战:安装ElasticSearch 和常用操作命令
概叙 科普文:深入理解ElasticSearch体系结构-CSDN博客 Elasticsearch各版本比较 ElasticSearch 单点安装 1 创建普通用户 #1 创建普通用户名,密码 [roothlink1 lyz]# useradd lyz [roothlink1 lyz]# passwd lyz#2 然后 关闭xshell 重新登录 ip 地址…...
React-Native 宝藏库大揭秘:精选开源项目与实战代码解析
1. 引言 1.1 React-Native 简介 React-Native 是由 Facebook 开发的一个开源框架,它允许开发者使用 JavaScript 和 React 的编程模型来构建跨平台的移动应用。React-Native 的核心理念是“Learn Once, Write Anywhere”,即学习一次 React 的编程模型&am…...
数据结构:二叉树(链式结构)
文章目录 1. 二叉树的链式结构2. 二叉树的创建和实现相关功能2.1 创建二叉树2.2 二叉树的前,中,后序遍历2.2.1 前序遍历2.2.2 中序遍历2.2.3 后序遍历 2.3 二叉树节点个数2.4 二叉树叶子结点个数2.5 二叉树第k层结点个数2.6 二叉树的深度/高度2.7 二叉树…...
召唤生命,阻止轻生——《生命门外》
本书的目的,就是阻止自杀!拉回那些深陷在这样的思维当中正在挣扎犹豫的人,提醒他们珍爱生命,让更多的人,尤其是年轻人从执迷不悟的犹豫徘徊中幡然醒悟,回归正常的生活。 网络上抱孩子跳桥轻生的母亲&#…...
JVM:栈上的数据存储
文章目录 一、Java虚拟机中的基本数据类型 一、Java虚拟机中的基本数据类型 在Java中有8大基本数据类型: 这里的内存占用,指的是堆上或者数组中内存分配的空间大小,栈上的实现更加复杂。 Java中的8大数据类型在虚拟机中的实现:…...
C#实战 - C#实现发送邮件的三种方法
作者:逍遥Sean 简介:一个主修Java的Web网站\游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有疑问和建议,请私信或评论留言! 前言 当使用 C# 编程…...
数模原理精解【5】
文章目录 二元分布满足要求边际分布条件概率例子1例子2 损失函数概率分布期望值例 参考文献 二元分布 满足要求 连续情况下, φ ( x , y ) \varphi (x,y) φ(x,y)为随机变量 X 、 Y X、Y X、Y的联合概率分布(二元分布),如果以下条件满足: …...
C语言篇——使用运算符将16进制数据反转
比如:将一个16进制0xFD,即11111101,反向,输出10111111,即0xBF。 #include <stdio.h>unsigned char reverseBits(unsigned char num) {unsigned char reverse_num 0;int i;for (i 0; i < 8; i) {if ((num &…...
2025年和2024CFA一级SchweserKaplan Notes 全集 (内附分享链接)
CFA一级notes百度网盘下载 2024年和2025年 CFA一级考纲已经正式发布,相比与老考纲,新考纲变化实在不算小。 2024年和2025年 CFA一级notes完整版全 https://drive.uc.cn/s/6394c0b6b1a54?public1 2024年和2025年 cfa二级notes完整版全 https://driv…...
B树的实现:代码示例与解析
B树的实现:代码示例与解析 引言 B树是一种自平衡的树数据结构,广泛应用于文件系统和数据库系统中。它是一种多路搜索树,旨在保持数据有序并允许高效的查找、插入和删除操作。本文将深入探讨B树的实现,提供完整的代码示例和详细的…...
HCIA总结
一、情景再现:ISP网络为学校提供了DNS服务,所以,DNS服务器驻留在ISP网络内,而不再学校网络内。DHCP服务器运行在学校网络的路由器上 小明拿了一台电脑,通过网线,接入到校园网内部。其目的是为了访问谷歌网站…...
软件测试_接口测试面试题
接口测试是软件测试中的重要环节,它主要验证系统不同模块之间的通信和数据交互是否正常。在软件开发过程中,各个模块之间的接口是实现功能的关键要素,因此对接口进行全面而准确的测试是确保系统稳定性和可靠性的关键步骤。 接口测试的核心目…...
C++初阶学习第五弹——类与对象(下)
类与对象(上):C初阶学习第三弹——类与对象(上)-CSDN博客 类和对象(中):C初阶学习第四弹——类与对象(中)-CSDN博客 一.赋值运算符重载 1.1 运算符重载 C为…...
最低工资标准数据(2001-2023年不等)、省市县,整理好的面板数据(excel格式)
时间范围:2001-2022年 具体内容:一:最低工资数据标准时间:2012-2021包含指标: 省份城市/区县小时最低工资标准(非全日制)月最低工资标准实施日期 样例数据: 二:各省最低…...
计算机毕业设计选题推荐-戏曲文化体验系统-Java/Python项目实战
✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...
【深度学习】CosyVoice,论文
CosyVoice_v1.pdf 文章目录 CosyVoice: A Scalable Multilingual Zero-shot Text-to-speech Synthesizer based on Supervised Semantic Tokens摘要1 引言2 CosyVoice: 使用监督语义标记的可扩展TTS模型2.1 用于语音的监督语义标记2.2 用于TTS的大型语言模型2.3 最优传输条件流…...
PHP8.3.9安装记录,Phpmyadmin访问提示缺少mysqli
ubuntu 22.0.4 腾讯云主机 下载好依赖 sudo apt update sudo apt install -y build-essential libxml2-dev libssl-dev libcurl4-openssl-dev pkg-config libbz2-dev libreadline-dev libicu-dev libsqlite3-dev libwebp-dev 下载php8.3.9安装包 nullhttps://www.php.net/d…...
[译] 深入浅出Rust基金会
本篇是对 RustConf 2023中的Rust Foundation: Demystified这一视频的翻译与整理, 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. 大家好,我是Sage Griffin,我的代词是they/them。我今天来这里是要谈谈Rust基金会。 要了解基金会实际做什么,我们需要理解美国国内税收…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
