Java集合(3:Set和Map)
文章目录
- Set
- 概述
- 哈希值
- HashSet去重原理
- LinkedHashSet
- TreeSet
- 自定义排序规则
- Map
- 概述
- Map的基本方法
- Map集合的获取功能
- 哈希表
- HashMap
- 底层源码
- 特点
- 注意
Set
概述
- Set集合也是一个接口,继承自Collection,与List类似,都需要通过实现类来进行操作。
特点:
- 不允许包含重复的值
- 没有索引(就不能使用普通的for循环进行遍历)
import java.util.HashSet;
import java.util.Set;public class Demo01 {public static void main(String[] args) {//使用多态,父类的引用指向子类对象Set<String> set = new HashSet<>();//添加元素set.add("黄固");set.add("欧阳锋");set.add("段智兴");set.add("洪七公");set.add("段智兴");System.out.println(set);//打印集合//[洪七公, 黄固, 欧阳锋, 段智兴]//HashSet集合对于元素的读写顺序不做保证//相同的元素,多次存储,只能保留一个,并且不会报错//List集合可以存储重复元素,Set集合不行}
}
例:双色球
import java.util.Random;
import java.util.TreeSet;public class Demo02 {public static void main(String[] args) {Random ran = new Random();//创建随机类对象int blueBall = ran.nextInt(16) + 1;
// HashSet<Integer> redBalls = new HashSet<>();//创建集合用来存储红球TreeSet<Object> redBalls = new TreeSet<>();//TreeSet集合自带排序规则while (redBalls.size() < 6){redBalls.add(ran.nextInt(33) + 1);//将当前生成的红球直接存进集合中//因为Set集合不能存储重复的元素,所以去重的操作可以省略不做。}System.out.println("红球:" + redBalls + "篮球 [" + blueBall + "]");}
}
哈希值
Set集合的去重原理使用的是哈希值。
哈希值就是JDK根据对象地址 或者 字符串 或者数值 通过自己内部的计算出来的一个整数类型数据
public int hashCode() - 用来获取哈希值,来自于Object顶层类
对象的哈希值特点:
- 同一个对象多次调用hashCode()方法,得到的结果是相同的。
- 默认情况下,不同的对象的哈希值也是不同的(特殊情况除外)
public class Demo03 {public static void main(String[] args) {//相同对象哈希值相同System.out.println("张三".hashCode());//774889System.out.println("张三".hashCode());//774889//不同对象哈希值不同System.out.println(new Object().hashCode());System.out.println(new Object().hashCode());//不同的对象的哈希值也有可能相同,例外情况System.out.println("辂鹅".hashCode());//1179395System.out.println("较鸦".hashCode());//1179395System.out.println("辄鸇".hashCode());//1179395System.out.println("辅鷨".hashCode());//1179395}
}
HashSet去重原理
HashSet集合的特点:
- 底层结构是“哈希表”
- 集合对于读写顺序不做保证
- 没有索引
- Set集合中的内容不能重复
public class Demo04 {public static void main(String[] args) {HashSet<Student> set = new HashSet<>();//添加元素set.add(new Student("黄固",28));set.add(new Student("欧阳锋",38));set.add(new Student("段智兴",48));set.add(new Student("洪七公",40));set.add(new Student("段智兴",48));//从程序的角度来考虑,两个段智兴不是同一个对象,都有自己的存储空间,所以哈希值也不一样。for (Student stu : set) {System.out.println(stu);}/*重写hashcode和equalsStudent{name='段智兴', age=48}Student{name='欧阳锋', age=38}Student{name='洪七公', age=40}Student{name='黄固', age=28}*/}
}
LinkedHashSet
特点:
- LinkedHashSet是哈希表和链表实现的Set接口,具有可预测的读写顺序。
- 有链表来保证元素有序
- 有哈希表来保证元素的唯一性
public class Demo05 {public static void main(String[] args) {LinkedHashSet<String> set = new LinkedHashSet<>();//添加元素set.add("黄固");set.add("欧阳锋");set.add("段智兴");set.add("洪七公");set.add("段智兴");//重复的元素不能存进去System.out.println(set);//打印集合 [黄固, 欧阳锋, 段智兴, 洪七公]}
}
TreeSet
- TreeSet集合底层实际上是一个TreeMap
- TreeMap集合底层是一个二叉树。
- 放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。
- TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序。
import java.util.TreeSet;
public class TreeSetTest02 {public static void main(String[] args) {// 创建一个TreeSet集合TreeSet<String> ts = new TreeSet<>();// 添加Stringts.add("zhangsan");ts.add("lisi");ts.add("wangwu");ts.add("zhangsi");ts.add("wangliu");// 遍历for(String s : ts){// 按照字典顺序,升序!System.out.println(s);}/*lisiwangliuwangwuzhangsanzhangsi*/TreeSet<Integer> ts2 = new TreeSet<>();ts2.add(100);ts2.add(200);ts2.add(900);ts2.add(800);ts2.add(600);ts2.add(10);for(Integer elt : ts2){// 升序!System.out.println(elt);}}
}
自定义排序规则
对于自定义的类无法排序,因为类中对象之间没有比较规则,不知道谁大谁小。
import java.util.TreeSet;public class TreeSetTest04 {public static void main(String[] args) {Customer c1 = new Customer(32);Customer c2 = new Customer(20);Customer c3 = new Customer(30);Customer c4 = new Customer(25);// 创建TreeSet集合TreeSet<Customer> customers = new TreeSet<>();// 添加元素customers.add(c1);customers.add(c2);customers.add(c3);customers.add(c4);// 遍历for (Customer c : customers){System.out.println(c);}}
}// 放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
// 并且实现compareTo方法。equals可以不写。
class Customer implements Comparable<Customer>{int age;public Customer(int age){this.age = age;}// 需要在这个方法中编写比较的逻辑,或者说比较的规则,按照什么进行比较!// k.compareTo(t.key)// 拿着参数k和集合中的每一个k进行比较,返回值可能是>0 <0 =0// 比较规则最终还是由程序员指定的:例如按照年龄升序。或者按照年龄降序。@Overridepublic int compareTo(Customer c) { // c1.compareTo(c2);return c.age - this.age;}public String toString(){return "Customer[age="+age+"]";}
}
匿名内部类方式
public class TreeSetTest05 {public static void main(String[] args) {
// TreeSet<Student> ts = new TreeSet<>();//默认排序规则TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {int res = o1.getAge() - o2.getAge();return 0 == res ? o1.getName().compareTo(o2.getName()) : res;//三目运算符 等于零用姓名排序}});//默认排序规则//添加元素ts.add(new Student("Andy",19));ts.add(new Student("Jack",18));ts.add(new Student("Tom",21));ts.add(new Student("Lucy",17));ts.add(new Student("Bob",21)); //当年龄相同时,按照姓名的字典顺序排序for (Student stu : ts) {System.out.println(stu);}}
}
Comparable和Comparator怎么选择呢?
当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实现Comparable接口。
如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
Map
概述
双列集合:用来存储键值对的集合。
- interface Map<K,V> : K(key)键 ,V(value)值
- 将键映射到值的对象,不能出现重复的键,每个键最多可以映射到一个值
1、Map和Collection没有继承关系。
2、Map集合以key和value的方式存储数据:键值对
key和value都是引用数据类型。
key和value都是存储对象的内存地址。
key起到主导的地位,value是key的一个附属品。
Map的基本方法
方法名 | 说明 |
---|---|
V put(K key,V value) | 设置键值对 |
V remove(Object key) | 删除元素 |
void clear() | 清空集合 |
boolean containsKey(Object key) | 判断键是否存在,存在则返回true |
boolean containsValue(Object value) | 判断值是否存在,存在则返回true |
boolean isEmpty() | 判断集合是否为空 |
int size() | 获取集合元素个数 |
import java.util.HashMap;
import java.util.Map;public class Map01 {public static void main(String[] args) {Map<String,String> map = new HashMap<>();map.put("STU001","Andy");map.put("STU002","Jack");map.put("STU003","Tom");map.put("STU004","Bob");map.put("STU004","Smith");//设置(修改)//如果键不存在,则表示添加元素。如果键存在,则表示设置值。//删除System.out.println(map.remove("STU003")); //Tom//判断是否包含System.out.println(map.containsKey("STU003")); //falseSystem.out.println(map.containsKey("STU004")); //trueSystem.out.println("-----------------------");System.out.println(map.containsValue("Tom")); //falseSystem.out.println(map.containsValue("Smith")); //trueSystem.out.println("-----------------------");System.out.println(map.isEmpty());//判断集合是否为空 falsemap.clear();//清空集合System.out.println(map.isEmpty()); //trueSystem.out.println(map); //{}}
}
Map集合的获取功能
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class map_get {public static void main(String[] args) {Map<String,String> map = new HashMap<>();map.put("STU001","Andy");map.put("STU002","Jack");map.put("STU003","Tom");map.put("STU004","Bob");//get通过键获取值System.out.println(map.get("STU003"));System.out.println("------------------");//keySet 获取所有键的Set集合Set<String> keySet = map.keySet();System.out.println(keySet);//values 获取所有值的Collection集合Collection<String> values = map.values();System.out.println(values);//entrySet 获取所有键值对对象的Set集合Set<Map.Entry<String, String>> es = map.entrySet();//Map集合通过entrySet()方法转换成的这个Set集合,Set集合中元素的类型是 Map.Entry<K,V>//Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态内部类System.out.println(es);//[STU001=Andy, STU003=Tom, STU002=Jack, STU004=Bob]for (Map.Entry<String, String> entry:es){System.out.println("key:"+entry.getKey()+" "+"value:"+entry.getValue());}/*key:STU001 value:Andykey:STU003 value:Tomkey:STU002 value:Jackkey:STU004 value:Bob*/}
}
哈希表
通过 数组 + 链表 实现的一种数据结构
哈希表的构造方法的参数是一个长度为16个元素的数组,通过哈希值 % 16 的值,作为头节点在数组中选择对应的位置,就形成了哈希表。
HashMap
底层源码
public class HashMap{// HashMap底层实际上就是一个数组。(一维数组)Node<K,V>[] table;// 静态的内部类HashMap.Nodestatic class Node<K,V> {final int hash; // 哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法,可以转换存储成数组的下标。)final K key; // 存储到Map集合中的那个keyV value; // 存储到Map集合中的那个valueNode<K,V> next; // 下一个节点的内存地址。}}
特点
-
1、无序,不可重复。
为什么无序? 因为不一定挂到哪个单向链表上。
不可重复是怎么保证的? equals方法来保证HashMap集合的key不可重复。
如果key重复了,value会覆盖。 -
2、放在HashMap集合key部分的元素其实就是放到HashSet集合中了。
所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法。 -
3、HashMap集合的默认初始化容量是16,默认加载因子是0.75
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组以二叉树开始扩容。
重点,记住:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的,
这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。
注意
1.向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法! equals方法有可能调用,也有可能不调用。 拿put(k,v)举例,什么时候equals不会调用?
k.hashCode()方法返回哈希值, 哈希值经过哈希算法转换成数组下标。 数组下标位置上如果是null,equals不需要执行。 拿get(k)举例,什么时候equals不会调用? k.hashCode()方法返回哈希值, 哈希值经过哈希算法转换成数组下标。 数组下标位置上如果是null,equals不需要执行。
4.假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成了 纯单向链表。
这种情况我们成为:散列分布不均匀。什么是散列分布均匀?
假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的, 是散列分布均匀的。假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题? 不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。 也是散列分布不均匀。散列分布均匀需要你重写hashCode()方法时有一定的技巧。
相关文章:

Java集合(3:Set和Map)
文章目录 Set概述哈希值HashSet去重原理LinkedHashSetTreeSet自定义排序规则 Map概述Map的基本方法Map集合的获取功能哈希表HashMap底层源码 特点注意 Set 概述 Set集合也是一个接口,继承自Collection,与List类似,都需要通过实现类来进行操…...

【Golang】Gin框架中如何定义路由
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

CPU内存飙升
CPU 飙升介绍 CPU 飙升是指中央处理器(CPU)的使用率在短时间内急剧上升,达到一个较高的水平。正常情况下,CPU 会根据系统和应用程序的需求合理分配资源,使用率会在一定范围内波动。但当 CPU 飙升时,可能会导…...

【Java】LinkedList实现类的使用
LinkedList实现类的使用 package com.star.test04;import java.util.Iterator;import java.util.LinkedList;/** * author : Starshine */public class Test { //这是main方法,程序的入口 public static void main(String[] args) { /* LinkedL…...

创建人物状态栏
接下来,我们来尝试制作一下我们的UI,我们会学习unity基本的UI系统 ************************************************************************************************************** 我们要先安装一个好用的插件到我们的unity当中,帮助…...

django5入门【01】环境配置
注意: ⭐前提:安装了annaconda(python版本管理工具),如果没有安装,强烈建议安装一下!!!操作: 前言: 这里新创建一个名为“python_3.11_start_dja…...

1000集《楼兰》系列短剧开机仪式在疆举行,开启全球传播新篇章
2024年10月18日,光明媚,秋风送爽。 在这个收获的季节里,倍受期待的楼兰系列短剧《楼兰之天女归来》和《楼兰之时空秘宝》在新疆吐鲁番东方红卓览文化博物馆举行了隆重的开机仪式,正式拉开了摄制的序幕。 1000集《楼兰》系列短剧…...

【景观生态学实验】实验五 景观生态脆弱性评价
实验目的 1.学习层次分析模型思路,对丹江口库区2000年景观生态脆弱性评价建模:通过实验课的学习,深入理解层次分析(Analytic Hierarchy Process,AHP)理论与模型,了解其在决策问题中的应用&…...

ChatGPT 现已登陆 Windows 平台
今天,OpenAI 宣布其人工智能聊天机器人平台 ChatGPT 已开始预览专用 Windows 应用程序。OpenAI 表示,该应用目前仅适用于 ChatGPT Plus、Team、Enterprise 和 Edu 用户,是一个早期版本,将在今年晚些时候推出"完整体验"。…...

和鲸社区数据科学实训季,西安交通大学圆满收官,西安,后会有期!
和鲸社区数据科学实训季活动已走进数十家高校,在西安的收官之站,落定西安交通大学管理学院,为本次西安之旅画上了圆满的句号。 和鲸社区 2024秋 数据科学实训季以“帮助同学积累真实场景项目经验”为出发点,提供 60 个数据科学实践…...

工作使用篇:如何在centos系统中安装anaconda
在CentOS 7上安装Anaconda的步骤如下: 1. 下载Anaconda 首先,你需要下载Anaconda的安装脚本。可以使用wget命令从Anaconda的官网获取最新版本的安装脚本。打开终端并运行以下命令: wget https://repo.anaconda.com/archive/Anaconda3-2024…...

qt creator 转 visual stdio 项目调试
因果 大家在使用qt creator调试程序时,会出现未知错误,比如下图,直接release运行就没有问题。由于调试复杂程序,使用qt creator都感觉不如vs,会报未知中断。 所以有了从qt creator转换到 visual stdio来调试的想法。…...

django5入门【02】创建新的django程序
注意: ⭐前提:已经安装了python以及django所依赖的包1、通过django-admin管理工具在命令行创建Django应用程序,创建命令如下: django-admin startproject ProjectName❓ 疑问:除了使用命令行创建django程序外&#x…...

乐趣无限,十个让你沉浸的“摸鱼”网站
在繁忙的生活中,我们总需要一些摸鱼时刻,来为紧绷的神经松绑。无论是工作间隙的小憩,还是下班后的放松,适当的摸鱼不仅能提升效率,还能让生活充满乐趣。今天,我为大家推荐几个绝对能让你乐在其中的网站&…...

ubuntu22.04 桌面系统怎么搭建一个esp-idf的项目,搭建开发环境
详细介绍如何在 Ubuntu 22.04 桌面系统上搭建 ESP-IDF 的开发环境,并创建一个 ESP-IDF 项目。以下内容将涵盖从环境准备到项目创建和编译的所有步骤。 目录 环境准备 1.1 更新系统1.2 安装必要的工具和依赖项 安装 ESP-IDF 2.1 克隆 ESP-IDF 仓库2.2 运行安装脚本 …...

iOS Swift逆向——deMangle过程中的偏移计算
碰到好多函数最开始都会调用这个函数,xref了一下,发现有上万个xref。 __int64 __fastcall sub_1000B6ED0(__int64 *a1) {__int64 result; // x0result *a1;if ( result < 0 ){result swift_getTypeByMangledNameInContext((char *)a1 (int)result…...

国产大模型基础能力大比拼 - 计数:通义千文 vs 文心一言 vs 智谱 vs 讯飞-正经应用场景的 LLM 逻辑测试
在大语言模型(LLM)不断涌现的时代,如何评估这些国产大模型的逻辑推理能力,尤其是在处理基础计数问题上的表现,成为了一个备受关注的话题。随着越来越多的国产大模型进入市场,比较它们在不同任务中的表现尤为…...

YOLO11改进 | 注意力机制 | 正确的 Self-Attention 与 CNN 融合范式,性能速度全面提升【独家创新】
秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 卷积和自注意力是两种强大的表征学习技术…...

0基础学java之Day11
二维数组 静态二位数组 理解:二维数组中包含了多个一维数组 声明: 数据类型 变量名;--推荐 数据类型 变量名; //静态初始化1//String[][] names new String[][]{{"小红","小绿","小蓝"},{"小黄","小紫…...

python主流框架Django:ORM框架关联查询与管理器
目录 注意 使用前要调用之前的模型类 F对象 Q对象 聚合函数 排序 关联查询(连表查询) 修改 删除 查询集 QuerySet 注意 使用前要调用之前的模型类 F对象 之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢? 答:使用 "F对象&quo…...

如何有效维护您的WordPress在线商店内容:提高客户参与度与转化率的实用技巧
在电子商务领域,内容为王。新鲜、相关且有吸引力的内容能显著提升客户参与度和转化率。本文将探讨如何有效更新和维护您的在线商店内容,确保客户始终获得最佳体验。 定期更新产品信息 产品描述 产品描述是吸引客户和促成销售的关键。定期检查并更新产…...

【Java】认识异常
1.异常概念与体系结构 1.1异常的概念 在我们日常开发中,代码都是尽可能完善,但是难免会出现一些奇奇怪怪的问题。而这些奇奇怪怪的问题可能很难通过代码去控制,比如格式不对会报错,网络不好也会报错等。 在Java中,将…...

20 Shell Script输入与输出
标出输入、标准输出、错误输出 一、程序的基本三个IO流 一)文件描述符 任何程序在Linux系统中都有3个基本的文件描述符 比如: cd/proc/$$/fd 进入当前shell程序对于内核在文件系统的映射目录中: [rootlocalhost ~]# cd /proc/$$/fd [rootlocalhos…...

HCIP-HarmonyOS Application Developer 习题(十六)
(判断)1、HiLink通过分布式软总线的方式连接所有设备,强能力设备可对弱能力设备进行设备虚拟化,将弱设备当做本机设备直接调用。 答案:错误 分析:HiLink 主要针对的是应用开发者与第三方设备开发者…...

没有什么可以抵达乌托邦,包括AI
本文为《智人之上:从石器时代到AI时代的信息网络简史》书评 可以说,尤瓦尔赫拉利又一次让我们获得了理解人类文明的新视角。 这是他一直以来都在做的:构建理解人类文明史的新知识框架。从此前的《人类简史》《未来简史》《今日简史》,到今天的新书《智人之上》,他一直保…...

家庭事务管理系统|基于java和vue的家庭事务管理系统设计与实现(源码+数据库+文档)
家庭事务管理系统 目录 基于java和vue的家庭事务管理系统 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师,阿里云…...

doris创建异步物化视图(加速数据低频变更的复杂实时计算)
异步物化视图,可以把那些每次实时计算非常耗时的,而需要计算的数据变更比较低频的这些计算创建对应的异步物化视图,当相关数据变化的时候触发异步任务去更新计算结果,或者定时计算也可以。例如该处示范为计算订单的订单标识&#…...

PhpSpreadsheet创建带复杂表头的excel数据
目录 一:背景 二:excel表头数据实现 三:excel渲染数据实现: 四:最终效果如下: 一:背景 最近需要统计一些数据,导出到excel,主要是一些区域的人员销售统计数据,涉及到复杂的表头和…...

BurpSuite渗透工具的简单使用
BurpSuite渗透工具 用Burp Suite修改请求 step1: 安装Burp Suite。官网链接:Burp Suite官网 step2: 设置代理 step3: 如果要拦截https请求,还需要在客户端安装证书 step4: 拦截到请求可以在Proxy ->…...

洞察云上风险,主机安全尽在掌握
在实战攻防演练中,主机一直是攻击方的最终目标。作为网络架构中的重要组成部分,主机包含了大量的敏感数据、关键服务和系统资源。同时主机拥有网络资源的访问权限,攻击者通过入侵主机获得权限,进而控制整个网络或系统。因此做好主…...