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

news2024/12/25 12:41:54

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可以有多个是null
        map.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可以有多个是null
        map.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是不可重复的,故会返回对应的value
        System.out.println(map.get("2"));//囿于pain
        System.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$EntrySet

        for(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  和  values
        Iterator iterator = set1.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
        //输出
//        1
//        2

        Iterator 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"));//jackon

        map.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   entrySet
        System.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--增强for
        Set keySet = map.keySet();
        System.out.println("==========第一种遍历方式===========");
        for (Object key : keySet) {
            //先获取value
            Object 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;
    }

    @Override
    public 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.coloradmin.cn/o/2119152.html

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

相关文章

从搜索热度上看Arcgis的衰退

Arcgis已被qgis快速赶上 google trends是一个google综合了每日的搜索情况的统计网站&#xff0c;可以追踪从2004年开始各个关键字的搜索热度。 我用arcgis和qgis作为对比&#xff0c;简单探索了arcgis和qgis的全球相关热度。 假设&#xff0c;搜索arcgis越高的区域&#xff…

机器学习 第8章 集成学习

目录 个体与集成BoostingBagging与随机森林Bagging随机森林 结合策略平均法投票法学习法 个体与集成 定义&#xff1a;集成学习&#xff0c;也叫多分类器系统、基于委员会的学习等&#xff0c;它是一种通过结合多个学习器来构建一个更强大的学习器的技术。如下图所示 在这里&a…

轨道交通系统详解,以及地铁如何精准停靠站台

ATC系统 全称“自动列车控制系统”&#xff0c;Automatic Train Control&#xff0c;ATC ATC是地铁运行的核心系统&#xff0c;它包括列车自动防护&#xff08;ATP&#xff09;、列车自动运行&#xff08;ATO&#xff09;和列车自动监控&#xff08;ATS&#xff09;三个子系统。…

嵌入式day41

哈希表 将要存储的数据的关键字和位置建立对应的关系&#xff0c;通过哈希函数&#xff08;散列函数&#xff09;将数据映射到存储的位置&#xff0c;方便快速查找 哈希冲突/哈希矛盾&#xff1a; key1 ! key2 f(key1) f(key2) 解决方法&#xff1a; 链地址法 算法 解决…

都2024年了还不明白Redis持久化?RDB文件、AOF文件、AOF重写

都2024年了&#xff0c;不会还有人不知道redis的RDB和Aof吧&#xff1f;不知道没关系&#xff0c;看完这篇文章我相信你就会有个大概的了解和认识了 1. Redis持久化 1.1 持久化概念 Redis本身是一个基于内存的数据库&#xff0c;它提供了RDB持久化、AOF持久化两种方式&#…

黑神话,XSKY 星飞全闪单卷性能突破310万

当下&#xff0c;云计算仍然是企业主要的基础架构&#xff0c;随着关键业务的逐步虚拟化和云化&#xff0c;对于块存储的性能要求也日益提高。企业对于低延迟、高稳定性的存储解决方案的需求日益迫切。为了满足这些日益增长的 IO 密集型应用场景&#xff0c;众多云服务提供商正…

大奖收割机!望繁信科技荣获年度技术创新和应用品牌奖

2023年8月14日&#xff0c;第七届GAIR全球人工智能与机器人大会在新加坡如期举行。 会上公布了「GAIR 2023 GPT Pioneer 5」榜单&#xff0c;望繁信科技凭借完全自主研发的流程智能平台&#xff0c;以及一系列在头部企业中的成功实践案例&#xff0c;与百度智能云、阿里云、知…

vector 容器基础操作及用法

目录 vector 容器基础操作及用法 一&#xff1a;定义及初始化 二&#xff1a;添加数据 三&#xff1a;删除数据 vector 容器基础操作及用法 CSTL是一个非常强大的容器库&#xff0c;其中 vector 是最为常用也较为方便的容器之一&#xff0c;下面主要介绍一下 vector 的一些…

学习threejs,创建立方体,并执行旋转动画

文章目录 一、前言二、代码示例三、总结 一、前言 本文基于threejs&#xff0c;实现立方体的创建&#xff0c;并加入立方体旋转动画 二、代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>l…

数据同步方式何来“高级”与“低级”之说?场景匹配才是真理!

导读&#xff1a;数据同步方式的重要性对于数据集成领域的兴从业者不言而喻&#xff0c;选择正确的数据同步方式能让数据同步工作的成果事半功倍。目市面上的数据同步工具很多&#xff0c;提供的数据同步方式也有多种&#xff0c;不同的数据同步方式有什么区别&#xff1f;如何…

免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来!

目录 背景解决方案。1.使用自签证书&#xff08;浏览器报警、免费&#xff09;2.更换支持自签自续的CA机构&#xff08;免费&#xff09;3.付费选择CA机构 免费SSL证书正在逐渐被淘汰&#xff0c;证书部署自动化的发展趋势即将到来免费的SSL证书有以下弊端1.有效期短&#xff1…

Python的安装与配置并在本地盘符创建共享路径打造低成本私人云盘

文章目录 前言1.本地文件服务器搭建1.1.Python的安装和设置1.2.cpolar的安装和注册 2.本地文件服务器的发布2.1.Cpolar云端设置2.2.Cpolar本地设置 3.公网访问测试4.结语 前言 本文主要介绍如何在Windows系统电脑上使用python这样的简单程序语言&#xff0c;在自己的电脑上搭建…

Leetcode面试经典150题-98.验证搜索二叉树

解法都在代码里&#xff0c;不懂就留言或者私信 二叉树的递归套路&#xff0c;练练就习惯了 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this…

内联汇编 (28)

1 首先是基本的格式。 网上的截图&#xff1a; 命令换行使用 \n\t 这里的constraint 指的就是 寄存器。 r , m , 比较重要。 这里的输出的意思是 &#xff0c; 从汇编到 C语言。 输入指的是 从C语言到 汇编语言 这是个具体的例子 %1, %2,%3, 是指 从上往下算&#xff0c;…

【Canvas与电脑桌面】白褐橘三色立方桌面(1920*1080)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>白褐橘三色立方桌面Draft1</title><style type"text/c…

应用层协议-HTTPS协议

应用层协议-HTTPS协议 一.概述 HTTP协议&#xff1a;初衷未考虑到安全性 HTTPS是在HTTP的基础上对应用层数据进行加密操作&#xff0c;HTTPSHTTPSSL/TLS HTTPS &#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure [5]&#xff09;&#xff0c;是以安全为目标…

用于客户支持的 GenAI:探索 Elastic Support Assistant

作者&#xff1a;Chris Blaisure, Cory Mangini 我们很高兴地宣布推出 Elastic 的支持助手。本博客将带你了解我们最新的生成式 AI 工具以及它可以帮助你使用 Elastic 技术的一些常见场景。 Elastic 支持助手现已在 Support Hub 上可用 今天&#xff0c;我们宣布 Elastic 支持…

vue3的el-tree的default-checked-keys无法勾选的问题解决

前言:有些树形控件是需要默认勾选的 但是请求后渲染不显示 刷新外部的key值也没有用 看了一下文档 我们使用自带的方法来解决 <el-treenode-key"id":data"state.parentMenuList":default-checked-keys"state.checkIdList":check-on-click-n…

VBA高级应用30例应用3ListObject对象:循环列出当前工作表中的表

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

266-基于Xilinx Kintex-7 XC7K325T 的12路光纤Switch交换平台

一、板卡概述 该系统是由两块模块组成&#xff0c;分别是基于Xilinx公司的FPGAXC7K325T-2FFG900 芯片&#xff0c;pin_to_pin兼容FPGAXC7K410T-2FFG900 的模块和一个FPGA夹层卡&#xff08;FMC&#xff09;模块。前者支持64bit DDR3容量2GByte&#xff0c;USB3.0接口;HPC的FMC连…