系列十三、集合

news2024/11/15 18:56:29

一、集合

1.1、概述

        集合与数组类似,只不过集合中的数据量可以动态的变化。

1.2、体系图

1.3、List集合

1.3.1、特点

        存放的数据可以重复且有序。

1.3.2、常见操作

/**
 * List集合常见操作
 * 
 */
@Test
public void listOperateTest() {
	List<String> cityList = new ArrayList<>(4);
	// 添加元素
	cityList.add("beijing");
	cityList.add("shanghai");
	cityList.add("guangzhou");
	cityList.add("shenzhen");

	// 获取集合中的某一个元素
	System.out.println("============================");
	String element = cityList.get(0);
	System.out.println("element = " + element);

	// 获取集合中的所有元素
	System.out.println("============================");
	System.out.println("所有元素:" + cityList);

	// 集合的长度
	System.out.println("============================");
	System.out.println("集合的长度:" + cityList.size());

	// 判断某个元素是否在集合中
	System.out.println("============================");
	boolean exist = cityList.contains("beijing");
	System.out.println("元素是否存在于集合中:" + exist);

	// 删除集合中的某个元素
	System.out.println("============================");
	System.out.println("删除之前:" + cityList);
	boolean remove = cityList.remove("beijing");
	System.out.println("删除结果:" + remove);
	System.out.println("删除之后:" + cityList);
}

1.3.3、ArrayList vs LinkedList

(1)ArrayList底层是数组,LinkedList底层是链表;

(2)ArrayList查询快、增删慢;LinkedList增删快、查询慢;

1.4、Set集合

1.4.1、特点

        存放的数据不能重复,无序。

1.4.2、常见操作

/**
 * Set集合常见操作
 */
@Test
public void setOperateTest() {
	HashSet<String> countrySet = new HashSet<>(4);
	// 添加元素
	countrySet.add("中国");
	countrySet.add("中国");
	countrySet.add("美国");
	countrySet.add("日本");

	// 查询所有元素
	System.out.println("====================");
	System.out.println("查询所有元素:" + countrySet);

	// 修改[删除]数据
	System.out.println("====================");
	boolean removeResult = countrySet.remove("日本");
	System.out.println("删除结果 = " + removeResult);
	boolean addResult = countrySet.add("德国");
	System.out.println("添加结果 = " + addResult);
	System.out.println("修改后的数据:" + countrySet);

	// 查询集合中元素的个数
	System.out.println("====================");
	System.out.println("查询集合中元素的个数:" + countrySet.size());

	// 遍历Set
	System.out.println("====================");
	for (String country : countrySet) {
		System.out.print(country + "\t");
	}
}

1.4.3、HashSet vs TreeSet

        HashSet的底层是哈希表、TreeSet的底层是二叉树。

1.5、Map集合

1.5.1、概述

        前面介绍的List、Set集合是单列集合,而Map是双列集合。

1.5.2、常见操作

/**
 * Map常见操作
 */
@Test
public void mapOperateTest() {
	Map<String, Object> map = new HashMap<>();
	// 添加元素:key-value、key必须唯一,不能重复!
	map.put("name", "李白");
	map.put("idNum", "411528199801012656");
	map.put("cardNo", "622202170205888999");
	map.put("email", "libai@qq.com");

	// 查询所有元素
	System.out.println("=======================");
	System.out.println("查询所有元素:" + map);

	// 根据key获取value
	System.out.println("=======================");
	Object value = map.get("name");
	System.out.println("根据key获取value:" + value);

	// 修改元素
	System.out.println("=======================");
	Object updateResult = map.put("name", "李太白");
	System.out.println("修改结果:" + updateResult);
	System.out.println("修改后集合中所有的元素:" + map);

	// 集合中元素的个数
	System.out.println("=======================");
	int size = map.size();
	System.out.println("集合中元素的个数:" + size);

	// 删除元素
	System.out.println("=======================");
	Object removeResult = map.remove("email");
	System.out.println("删除结果:" + removeResult);
	System.out.println("删除后集合中所有的元素:" + map);

	// 判断某个元素是否在集合中
	System.out.println("=======================");
	boolean keyExist = map.containsKey("idNum");
	boolean valueExist = map.containsValue("411528199801012656");
	log.info("key是否存在:{},value是否存在:{}", keyExist, valueExist);


	// 遍历集合
	System.out.println("=======================");
	for (Map.Entry<String, Object> entry : map.entrySet()) {
		System.out.println(entry.getKey() + ":" + entry.getValue());
	}
}

 

 二、集合相关的面试题

2.1、说一说Java中常见的集合

        Java中提供了大量的集合类,主要分为两大类,即:单列集合和双列集合,下面详细介绍:

第一个是Collection 属于单列集合,第二个是Map 属于双列集合。

在Collection中有两个子接口List和Set。在我们平常开发的过程中用的比较多像list接口中的实现类ArrarList和LinkedList。 在Set接口中有实现类HashSet和TreeSet。
在map接口中有很多的实现类,平时比较常见的是HashMap、TreeMap,还有一个线程安全的map:ConcurrentHashMap

2.2、List集合是如何扩容的

2.2.1、源码(部分)

2.2.2、详解

        ArrayList是一个数组结构的存储容器,默认情况下数组的长度是10个,当然我们也可以在构建ArrayList对象的时候指定初始长度,那么随着程序不断的往集合中添加元素,当添加的元素达到10个的时候,ArrayList里面就没有足够的容量来存储新的元素了,那么这个时候ArrayList就会触发自动扩容,扩容的流程大致如下:

(1)创建一个新的数组,那么这个数组的长度是原来的1.5倍;

(2)使用Arrays.copyOf()方法将老的数据拷贝到新的数组里面,接着再把当前需要添加的元素添加到当前数组里面,从而完成动态扩容的一个过程;

2.3、HashMap是如何扩容的

2.3.1、源码(部分)

2.3.2、详解

        当我们在创建一个集合对象的时候,实际上就是在内存里面一次性申请了一块内存空间,而这个内存空间的大小是在创建集合对象的时候指定的,对于Map集合而言,默认的初始大小为16,在实际开发中,随着不断的往集合中添加元素,会导致集合的容量不够,这个时候就会触发集合的自动扩容,那么具体是怎么扩容的呢?当集合中的元素达到某个阈值的时候,Map集合就会进行动态扩容,阈值的计算公式为:16 * 0.75 = 12,即默认情况下,当Map集合中的元素达到12的时候,将会触发Map容器的自动扩容机制,从而更好的满足存储更多数据的需求,也即当Map中元素的个数达到12的时候,将会触发第一次扩容,扩容后容器的容量变为原来的2倍,即32;第二次扩容的临界值为:32 * 0.75 = 24,即当Map集合中元素的个数达到24的时候,将会触发第二次扩容;其他依次类推...

        所以,当我们在创建集合对象的时候,要充分考虑集合中所存储元素的个数,防止容器频繁的扩容,影响系统的性能。

2.3.3、为什么扩容因子是0.75

        扩容因子表示hash表中元素的填充程度,扩容因子的值越大,那么就意味着触发扩容元素的个数会更多,虽然它的整体空间利用率比较高,但是hash冲突的概率也会随之增加,反过来说扩容因子的值越小,那么触发扩容元素的个数也就越小,hash冲突的概率也越小,但是对于内存空间的浪费就比较多了,而且还会增加扩容的频率,影响系统的性能,因此扩容因子值的设置,不宜过大也不宜过小。0.75这个值的来源和统计学里面的【泊松分布】有关系,HashMap里面是采用链式寻址的方式去解决hash冲突的,而为了避免链表过长带来的一个时间复杂度增加的情况,所以当链表的长度大于等于7的时候就会转化成红黑树,从而提升检索的效率,当扩容因子在0.75的时候,链表长度达到8的可能性几乎为0,也就是说负载因子设置为0.75比较好的达到了空间成本和时间成本的一个平衡。

2.4、HashSet是如何保证元素不重复的

2.4.1、概述

        前面的内容介绍了HashSet,它和其他单列集合一个显著的区别就是元素不重复,那么它是如何实现元素不重复的呢?

2.4.2、源码(部分)

构造方法:

add方法:

 

         

 

2.4.3、分析

        从源码可以看出,HashSet的内部其实是利用了HashMap来实现的,内部持有一个HashMap的引用,操作HashSet实际上底层是操作这个map,HashMap的key是唯一的,从上面的源码可以看出HashSet添加进去的值其实是作为HashMap的key,所以HashSet中的元素不会重复。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1369356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 +TS 安装使用pinia状态管理

目录 一.安装 1.下载安装依赖 2.创建src/stores/index.ts文件 3.创建src/stores/states.ts文件 4.创建src/stores/interface/index.ts文件 5.修改main.ts 6.目录结构如下 7.测试使用 8.去到首页点击按钮&#xff0c;打开控制台查看 一.安装 1.下载安装依赖 npm insta…

逆向数据宽度与符号

正数与负数的 刚好是半 所以 0 表示正数 1表示负数 有符号与无符号是程序员定的 并不是开头是1就表示负数 0表示正数 得看有无符号 双字 32bit 4字节

批量置入视频封面:一分钟教程,简单易学

在视频制作过程中&#xff0c;为视频添加引人注目的封面是吸引观众的关键。而当我们需要批量处理多个视频时&#xff0c;如何快速、准确地置入封面就显得尤为重要。本文将为您揭示这一高效技巧&#xff0c;让您在一分钟内学会批量置入视频封面&#xff0c;提升视频的吸引力与观…

C++学习笔记(二十七):c++ 动态数组vector及优化

c的动态数组vector是STL的内容&#xff0c;关于STL&#xff0c;有兴趣可自行网上搜索资料。本节主要介绍vector的基本内容以及vector的简单优化。vector当超过数组最大范围&#xff0c;需要往里面添加新的元素时&#xff0c;会在内存中创建一个比上一个更大的数组&#xff0c;将…

RT-Thread:ADC 框架应用,通过 STM32CubeMX 配置 STM32 ADC驱动

关键词&#xff1a;ADC,RT-Thread ADC,STM32 ADC应用 说明&#xff1a;本笔记是记录如何开启 RT-Thread 框架的ADC功能&#xff0c;使用系统自带的ADC函数&#xff0c;并通过 STM32CubeMX 配置 STM32 ADC驱动 。 1. 打开board.h 文件&#xff0c;找到ADC 使用配置的流程&…

CMake入门教程【核心篇】动态库与静态库的差别

😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 1.概述2.动态库(Shared Libraries)主要特点使用场景3.静态库(Static Libraries)主要特点

java继承Thread实现多线程

1、AdminController文件 package com.controller;import com.myThread.AdminThread; import org.springframework.web.bind.annotation.*;RestController CrossOrigin RequestMapping("/admin") public class AdminController{GetMapping("/{id}")public …

离线安装jenkins:使用rpm安装包

目录 一、安装jdk1.8二、安装yum软件包三、下载rmp安装包四、安装jenkins的rpm安装包五、创建jenkins文件目录六、设置环境变量七、配置jdk位置八、配置Jenkins配置文件九、启动Jenkins十、访问Jenkins十一、安装Jenkins插件 一、安装jdk1.8 根据博客Linux操作系统安装jdk1.8并…

Rollup-plugin-bundle-analyzer VS Rollup-plugin-visualizer

分析和可视化Rollup打包后的文件的插件 Rollup-plugin-bundle-analyzerRollup-plugin-visualizer Rollup-plugin-bundle-analyzer和Rollup-plugin-visualizer都是用于分析和可视化Rollup打包后的文件的插件&#xff0c;但它们在功能和使用方式上存在一些差异。 Rollup-plugi…

作业--day43

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数&#xff0c;将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c…

外包做了5个月,技术退步一大半了。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入深圳某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

麒麟操作系统缓存rpm包,制作离线yum源

缓存rpm包&#xff0c;以make为例 mkdir -p /data/yum yumdownloader --resolve --destdir/data/yum make制作离线yum包 yum install createrepo -y cd /data/yum createrepo .写yum配置文件/etc/yum.repos.d/local.repo [local-repo] namelocal-repo baseurlfile:///data/…

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)

一 使用临时节点实现分布式锁 1.1 代码截图 1.2 代码如下 由于zookeeper获取链接是一个耗时过程&#xff0c;这里可以在项目启动时&#xff0c;初始化链接&#xff0c;并且只初始化一次。借助于spring特性&#xff0c;代码实现如下&#xff1a; package com.atguigu.distri…

世微 AP5127 DC-DC降压恒流IC 输入12-24 输出9V 2A 车灯方案线路图

此方案应用领域&#xff1a;电动车&#xff0c;摩托车灯照明&#xff0c; 汽车灯照明&#xff0c;手电筒&#xff0c;LED照明等 AP5127 是一款 PWM 工作模式,高效率、外 围简单、内置功率管&#xff0c;适用于 12-100V 输入的高 精度降压 LED 恒流驱动芯片。输出功率可达 25W&a…

【排序算法】二、希尔排序(C/C++)

「前言」文章内容是排序算法之希尔排序的讲解。&#xff08;所有文章已经分类好&#xff0c;放心食用&#xff09; 「归属专栏」排序算法 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 希尔排序1.1 原理1.2 代码实现&#xff08;C/C&#xff09;1.3 特性总结 希尔排序 1.1…

spring Security源码讲解-WebSecurityConfigurerAdapter

使用security我们最常见的代码&#xff1a; Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().permitAll();http.authorizeRequests().antMatcher…

【Python】DataFrame 使用 concat 横向拼接出现两行问题

问题 在使用 DataFrame 中 concat 横向拼接两个只有一行的 DataFrame 时&#xff0c;最终的结果有两行。 如下图&#xff1a; 原始的 df 分别为&#xff1a; 指定横向合并后是&#xff1a; 这里可以看到是横向拼接了&#xff0c;但是并没有真正意义的横向拼接&#xff0c;而…

AI数字人虚拟现实产业的发展现状与展望

AI数字人虚拟现实产业是当今科技领域备受瞩目的发展方向之一。随着人工智能和虚拟现实技术的迅猛发展&#xff0c;人们对于数字形象的需求不断增加&#xff0c;AI数字人虚拟现实产业正应运而生。本文将从产业现状和未来展望两个方面来描绘AI数字人虚拟现实产业的发展。 首先&a…

编程学习课前准备

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 浏览器和文本编辑器安装 数据分析三大软件安装 操作系统要求 查看Windows系统版本和位数 查看操作系统账户信息 Windows目录显式设置 命令行界面使用 打开命令行 方法一&#xff1a; 方法二&#xff1a; 方法…

MT6762芯片性能参数介绍_MTK联发科处理器

MT6762采用台积电 12 nm FinFET 制程工艺&#xff0c;8* Cortex-A53架构&#xff0c;搭载Android9.0/11.0/12.0操作系统&#xff0c;主频最高达2.0GHz&#xff0c;提供更高阶的功能和出色的体验。 搭载PowerVR GE8329 GPU&#xff0c;运行频率高达 650MHz&#xff0c;实现 20&a…