Java小白一文讲清Java中集合相关的知识点(七)

LinkedHashSet

  • LinkedHashSet是HashSet的子类

  • LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表

    而在之前讲的HashSet中的链表是单向的哈,注意区分!

  • LinkedHashSet根据元素的hashcode值来决定元素的存储位置,同时使用链表维护元素的次序,

    这使得元素看起来是以插入的顺序保存的

  • LinkedHashSet不允许添加重复元素

  • 第一次向其中添加元素时,直接将数组table扩容到16,存放的结点类型是LinkedHashMap$Entry

    数组table是HashMap$Node[ ],但是存放的数据/元素

    是LinkedHashMap$Entry类型的,这其实就是数组的多态的体现;

        static class Entry<K,V> extends HashMap.Node<K,V> {//此中的before和after是进行双向链表的连接的//其继承关系是在内部类完成的Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}}

在这里插入图片描述

补充:

  • 当编写一个LinkedHashSet的应用实例时,比如让你创建一个Car类,然后创建好几辆车,有各自的名字和价格,要求如果名字和价格相等的话,无法加入到LinkedHashSet中去,这时候就要重写equals和hashCode方法,那么,有个问题,我如果只写二者其一,可不可以呢?即只保留equals或者hashCode; 答案是:不行,因为LinkedHashSet底层是HashMap,所以实现去重的源码部分是一样的,必须要equals和hashCode二者的值都相等,才符合去重条件,才会拒绝第二个,第三个equals和hashCode值都相等的Car对象的加入

        //注意,equals和hashCode两个方法少一个都无法实现去重,//因为其底层判断的时候就是要二者都相同才符合去重条件/**if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;*/
    

Map接口和常用方法

Map接口

  • Set和Map其实二者都是K-V存储,但是不同于Map,Set中的V采用的是PRESENT,所以我们只能在Set中自定义存储K,V会由底层自动实现,而Map中,K、V都是可以自定义存放的,so 这也是为什么说Set其实就是Map的原因;
  • Map与Collection并列存在,即二者是两大类,是同级关系,Map用于保存具有映射关系的数据:key-value
  • Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  • Map中的key不允许重复,原因和HashSet一样
    public static void main(String[] args) {Map map = new HashMap();map.put("1","kerwin");map.put("2","囿于pain");map.put("1","jas");//当有相同K时,就会等价替换System.out.println("map ="+map);//{1=jas, 2=囿于pain}//再加个重复的value,试试map.put("3","jas");System.out.println("map ="+map);
//      map ={1=jas, 2=囿于pain, 3=jas}}
  • Map中的value可以重复
  • Map的key可以为null,value也可以为null,注意key为null时,只能有一个,value为null时,可以有多个
    public static void main(String[] args) {Map map = new HashMap();map.put("1","kerwin");map.put("2","囿于pain");map.put("1","jas");//当有相同K时,就会等价替换System.out.println("map ="+map);//{1=jas, 2=囿于pain}//再加个重复的value,试试map.put("3","jas");System.out.println("map ="+map);
//      map ={1=jas, 2=囿于pain, 3=jas}map.put(null,null);System.out.println(map);
//     {null=null, 1=jas, 2=囿于pain, 3=jas}//key只能有一个是null,重复加入,会发生替换//value可以有多个是nullmap.put("4",null);map.put("5",null);map.put(null,"fulture");System.out.println(map);
//      {null=fulture, 1=jas, 2=囿于pain, 3=jas, 4=null, 5=null}}
  • 常用String类作为Map的key
  • key和value之间存在单向一对一的关系,即通过指定的key总能找到对应的value
    public static void main(String[] args) {Map map = new HashMap();map.put("1","kerwin");map.put("2","囿于pain");map.put("1","jas");//当有相同K时,就会等价替换System.out.println("map ="+map);//{1=jas, 2=囿于pain}//再加个重复的value,试试map.put("3","jas");System.out.println("map ="+map);
//      map ={1=jas, 2=囿于pain, 3=jas}map.put(null,null);System.out.println(map);
//     {null=null, 1=jas, 2=囿于pain, 3=jas}//key只能有一个是null,重复加入,会发生替换//value可以有多个是nullmap.put("4",null);map.put("5",null);map.put(null,"fulture");System.out.println(map);
//      {null=fulture, 1=jas, 2=囿于pain, 3=jas, 4=null, 5=null}//通过传入的key,由于key是不可重复的,故会返回对应的valueSystem.out.println(map.get("2"));//囿于painSystem.out.println(map.get(null));//fulture}
  • Map存放数据的key-value示意图,一对k-v是放在一个Node上的,又因为Node实现了Entry接口,有些书上也说一对k-v就是一个Entry

在这里插入图片描述

static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;....
}
  • K-V 为了方便程序员的遍历,还会创建EntrySet 集合,该集合存放的元素的类型是Entry, 而一个Entry对象就有k,v ,即Entry由Entr组成,而每个Entry包含一对K-V, EntrySet<Entry<K,V>> , 源码如下:
transient Set<Map.Entry<K,V>> entrySet;
  • entrySet中,定义的类型是Map.Entry ,但是实际上存放的还是HashMap$Node,这是因为Node实现了Map.Entry,即接口的多态,接口引用指向了实现了接口的类,源码即:

    static class Node<K,V> implements Map.Entry<K,V> {
    
  • 当把HashMap$Node 对象存放到 entrySet 就方便我们的遍历,因为 Map.Entry接口提供了重要的方法

    K getKey() V getValue()

    public static void main(String[] args) {Map map = new HashMap();map.put("1","kerwin");map.put("2","jackon");Set set = map.entrySet();System.out.println(set.getClass());//HashMap$EntrySetfor(Object obj : set){
//            System.out.println(obj.getClass());//为了从HashMap$Node 中取出k-v//1.先做一个向下转型Map.Entry entry = (Map.Entry)obj;System.out.println(entry.getKey()+" - "+entry.getValue());//  1 - kerwin//	2 - jackon}}
  • HashMap中的table表采用数组+链表+红黑树来维护,数组中存放Node类型数据,但是为了方便管理,其在底层也做了一层控制,将每个Node封装成一个Entry,然后将一个个Entry,放到EntrySet集合中去,这样实现的主要目的是方便管理;除此之外,还提供了一个KeySet集合,其中单独地封装了一个个的Node中的key,形成KeySet集合,同理,将所有的value抽取出来,封装成了一个Collection集合,源码如下:
public static void main(String[] args) {Map map = new HashMap();map.put("1","kerwin");Set set1 = map.keySet();System.out.println(set1.getClass());//HashMap$KeySet  是HashMap的内部类,负责管理键Collection values = map.values();System.out.println(values.getClass());//HashMap$Values  是HashMap的内部类,负责管理值//遍历下set1  和  valuesIterator iterator = set1.iterator();while(iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);}//输出
//        1
//        2Iterator iterator2 = values.iterator();while (iterator2.hasNext()) {Object obj = iterator2.next();System.out.println(obj);}//输出
//        kerwin
//        jackon
}

常用方法

  • put添加
  • remove根据键删除映射关系
  • get根据键获取值
  • size获取元素个数
  • isEmpty判断个数是否为0
  • clear清除
  • containsKey查找键是否存在
@SuppressWarnings({"all"})
public class Journey {public static void main(String[] args) {Map map = new HashMap();//添加map.put("1","kerwin");map.put("2","jackon");map.put(true,123);//删除map.remove(true);System.out.println(map);//{1=kerwin, 2=jackon}System.out.println(map.get("2"));//jackonmap.put(null,123);map.put(false,null);//获取元素个数System.out.println(map.size());//4//判断是否为空System.out.println(map.isEmpty());//false//查找键是否存在System.out.println(map.containsKey(false));//true//清除map.clear();System.out.println(map);//{}}
}

Map接口遍历方法

  • containsKey 查找键是否存在
  • keySet 获取所有的键
  • entrySet 获取所有的关系
  • values 获取所有的值
    public static void main(String[] args) {Map map = new HashMap();//添加map.put("1", "kerwin");map.put("2", "jackon");map.put(true, 123);map.put(null, 123);map.put(false, null);//查找键是否存在System.out.println(map.containsKey(false));//true//直接打印keySet  values   entrySetSystem.out.println(map.keySet());//[null, 1, 2, false, true]System.out.println(map.entrySet());//[null=123, 1=kerwin, 2=jackon, false=null, true=123]System.out.println(map.values());//[123, kerwin, jackon, null, 123]System.out.println("===================================");//迭代遍历打印Set keys = map.keySet();Iterator iterator = keys.iterator();System.out.println("keySet:");while(iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);}Collection values = map.values();Iterator iterator1 = values.iterator();System.out.println("values:");while (iterator1.hasNext()) {Object obj = iterator1.next();System.out.println(obj);}Set entry = map.entrySet();Iterator iterator2 = entry.iterator();System.out.println("entrySet:");while (iterator2.hasNext()) {Object obj = iterator2.next();System.out.println(obj);}/*** ===================================* keySet:* null* 1* 2* false* true* values:* 123* kerwin* jackon* null* 123* entrySet:* null=123* 1=kerwin* 2=jackon* false=null* true=123*/}

练习

在这里插入图片描述

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;@SuppressWarnings({"all"})
public class CodingDemo {public static void main(String[] args) {HashMap map = new HashMap();Employee emp1 = new Employee("小A", 20000, 1);Employee emp2 = new Employee("小B", 10000, 2);Employee emp3 = new Employee("小C", 15000, 6);Employee emp4 = new Employee("小D", 19000, 10);map.put(emp1.getId(),emp1);map.put(emp2.getId(),emp2);map.put(emp3.getId(),emp3);map.put(emp4.getId(),emp4);//实现遍历--keySet--增强forSet keySet = map.keySet();System.out.println("==========第一种遍历方式===========");for (Object key : keySet) {//先获取valueObject o = map.get(key);Employee emp = (Employee)o;if(emp.getSal()>18000){System.out.println(emp);}}//实现遍历--EntrySet---迭代器Set entrySet = map.entrySet();System.out.println("===========第二种遍历方式==============");Iterator iterator = entrySet.iterator();while (iterator.hasNext()) {Object obj  = iterator.next();Map.Entry entry = (Map.Entry)obj;Employee emp = (Employee) entry.getValue();if(emp.getSal()>18000){System.out.println(emp);}}}
}
@SuppressWarnings({"all"})
class Employee{private String name;private double sal;private int id;public Employee(String name, double sal, int id) {this.name = name;this.sal = sal;this.id = id;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", sal=" + sal +", id=" + id +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSal() {return sal;}public void setSal(double sal) {this.sal = sal;}public int getId() {return id;}public void setId(int id) {this.id = id;}
}

HashMap小结

  • Map接口的常用类:HashMap、Hashtable、Properities
  • HashMap是Map接口使用频率最高的实现类
  • HashMap是以key-value 对的方式(HashMap$Node类型)来存储数据
  • key不能重复,但是值可以重复,允许使用null键和null值
  • 如果添加相同的key,则会覆盖原来的key-value,等同于修改(key不会替换,value会替换)
  • 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的
  • HashMap没有实现同步,因此是线程不安全的,方法上没有做同步互斥操作,没有synchronized关键字修饰

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

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

相关文章

极限编程XP例题

答案&#xff1a;D 解析&#xff1a; 结对编程&#xff0c;一个人写代码&#xff0c;一个人看&#xff0c;由于是两个或两个以上的人负责&#xff0c;因此选项A 支持共同代码拥有和共同对系统负责是正确的 选项B 由于是一个人写一个人看&#xff0c;变相实现了代码审查 选项…

深入了解 GROW with SAP:它究竟是什么?

GROW with SAP 是一套综合全面的产品组合&#xff0c;包含一系列解决方案、加速采用服务、社区支持和学习资源&#xff0c;能够确保各种规模的企业成功采用 ERP 云软件。部署 GROW with SAP 后&#xff0c;企业可以采用 SAP S/4HANA Cloud Public Edition [ERP 公有云版]。在 S…

4 路由模式

路由模式 逻辑图 如果我们将生产环境的日志进行处理&#xff0c;而日志是分等级的&#xff0c;我们就按照 error waring info三个等级来讲解 一个消费者是处理【所有】&#xff08;info&#xff0c;error&#xff0c;warning&#xff09;的日志&#xff0c;用于做数据仓库&am…

Redis搭建集成

图示 正常来讲配置一主两从需要三台服务器,博主内存告急,就使用一台进行操作了,使用多台跟一台操作没有区别,只是多台不需要新建太多配置文件 一. 准备配置文件 如果你跟我一样是在一台服务器里面进行配置主从服务的,跟我一起操作即可 找到redis目录 在bin目录同位置创建一…

Linux驱动.之驱动开发思维,设备,驱动,总线分析思想,驱动的分类(字符设备,块设备,网络设备)

在stm32&#xff0c;裸机开发时&#xff0c;偏底层&#xff0c;跟寄存器打交道&#xff0c;有些MCU提供了库&#xff0c;库也还是操作寄存器的&#xff0c;通过配置寄存器&#xff0c; 配置各种工作模式&#xff0c;时钟&#xff0c;等等&#xff0c;交换数据等等。 Linux下驱…

Unity笔记之静态/动态合批

借用博主链接 一、静态合批 1、首先项目设置里面需要勾选静态合批 2、添加静态合批选项 3、至此就完成了&#xff0c;至于成功没有就要去分析器里面看了。 静态合批注意问题&#xff1a; 二、动态合批 1、首先项目设置里面需要勾选动态合批 2、调用 StaticBatchingUtilit…

给大家推荐好用的AI网站

地址&#xff1a;https://ai.ashuiai.com/auth/register?inviteCode8E8DIC1QCR 个人觉得挺好用的&#xff0c;可以免费&#xff0c;免费有限制次数&#xff0c;也可以会员升级200永久免费&#xff0c;我用的200永久免费。 可以在国内使用以下ai模型 回答问题更智能&#xff…

IBM中国研发部裁员:全球化背景下的IT产业变局与应对之道

裁员风波中的思考与机遇 前言了解霍尼韦尔的“东方服务东方”施耐德电气的“中国中心”战略对比与分析 中国信息技术(IT)行业展现出蓬勃发展的前景**政府支持与政策导向****技术创新与应用****市场规模与需求****人才培养与就业**国际化与开放合作总结 前言 如何看待IBM中国研发…

“冰山之下”:谁在成为车企的真正智能助手?

“其实我们一直扮演的角色就是数字化助手&#xff0c;也就是别人可以去挖金&#xff0c;我们给大家提供铲子&#xff0c;这是我们扮演的角色&#xff0c;而现在我们希望给大家提供最好的铲子。” 作者| 皮爷 出品|产业家 如果说AI发展的最鲜明印痕是什么&#xff1f;有人…

【原创教程】自动化工程案例01:8工位插针装配机03-程序解读

在前面两篇文章中&#xff0c;我们介绍了8工位设备每个工位的情况&#xff0c;然后我们介绍了触摸屏的情况&#xff0c;接着我们来看一下程序。关于一些实物照片不宜公开发表&#xff0c;需要的可以私信。 程序系统块设置 系统块中的模块实际上是我们所使用的的硬件设施 符号…

本地Linux服务器使用docker搭建DashDot并实现公网实时监测服务器信息

文章目录 前言1. 本地环境检查1.1 安装docker1.2 下载Dashdot镜像 2. 部署DashDot应用3. 本地访问DashDot服务4. 安装cpolar内网穿透5. 固定DashDot公网地址 前言 本篇文章我们将使用Docker在本地部署DashDot服务器仪表盘&#xff0c;并且结合cpolar内网穿透工具可以实现公网实…

HC-SR501人体红外传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 body_hw.h文件 body_hw.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 HC-SR501人体红外模块是基于红外线技术的自动控制模块&#xff0c;采用德国原装进口LHI77…

USB总线开关量DIO采集卡,24路数字量输入输出及32位计数器卡USB5801

阿尔泰科技 型号&#xff1a;USB5801 概述&#xff1a; 产品应用&#xff1a; 指标参数&#xff1a; 数字量 通道数 24路&#xff0c;每8路可配置成输入或输出 电气标准 TTL兼容 数字量输入 高电平的低电压&#xff1a;2V 低电平的高电压&#xff1a;0.8V 数字量输出 …

数据结构基础讲解(七)——数组和广义表专项练习

本文数据结构讲解参考书目&#xff1a; 通过网盘分享的文件&#xff1a;数据结构 C语言版.pdf 链接: https://pan.baidu.com/s/159y_QTbXqpMhNCNP_Fls9g?pwdze8e 提取码: ze8e 数据结构基础讲解&#xff08;六&#xff09;——串的专项练习-CSDN博客 个人主页&#xff1a;樱娆…

替代区块链

随着比特币的成功&#xff0c;人们逐渐意识到区块链技术的潜力&#xff0c;并随之出现了迅速的发展&#xff0c;各种区块链协议、应用程序和平台相应产生。 需要指出的是&#xff0c;在这种多元的局面下&#xff0c;很多项目迅速失去了它们的吸引力。事实上&#xff0c;有不少项…

ITK-高斯滤波

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 高斯滤波原理 高斯滤波&#xff08;Gaussian Blur&#xff09;是数字图像处理中常见的一种平滑滤波器&#xff0c;旨在通过模糊处…

Edge-Triggered模式:反应堆

Linux: Linux Code - Gitee.comhttps://gitee.com/RuofengMao/linux/tree/master/Reactor

yolov5-6.2 在 rk3399pro 上的移植

文章目录 一、搭建yolov5环境二、导出onnx模型三、安装 rknn-toolkit四、通过netron 查看 yolov5s.onnx 输出节点五、创建 onnx2rknn.py 文件六、通过toolkit将onnx转换为rknn模型七、在rk3399pro开发板上运行rknn模型 一、搭建yolov5环境 从yolov5官方仓库 ultralytics/yolov…

【DS18B20 简单开发】

DS18B20 是一种数字温度传感器&#xff0c;由 Maxim Integrated 生产。它提供了一个非常简单的方式来将温度测量集成到微控制器系统中。以下是关于 DS18B20 的一些关键特性&#xff1a; 单总线协议&#xff1a;DS18B20 使用单总线&#xff08;1-Wire&#xff09;数字通信协议&…

HTML添加文字

一、创建HTML5文档基本标签 <!DOCTYPE html> //定义文档类型 <html> //定义HTML文档<head> //定义关于文档的信息<title>文档标题</title> //定义文档的标题<meta charset"utf-8" /> //定义文档的字符编码</head&…