第十四章 集合(Set)

news2024/11/16 3:24:19

一、Set 接口(P518)

1.  Set接口基本介绍

(1)无序(添加和取出的顺序不一致),没有索引 
(2)不允许重复元素,所以最多包含一个 null

2. Set接口的常用方法

和 List 接口一样,Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一样。

3. Set接口的遍历方式

同 Collection 的遍历方式一样,因为 Set 接口是 Collection 接口的子接口
(1)可以使用选代器
(2)增强for
(3)不能使用索引的方式来获取

二、HashSet(P519)

1. Hashset 的说明

(1)HashSet 实现了 Set 接口
(2)HashSet 实际上是 HashMap

(3)可以存放null值,但是只能有一个 null
(4)HashSet 不保证元素是有序的,取决于 hash 后,再确定索引的结果
(5)不能有重复元素/对象。

2. Hashset底层机制源码说明(P522)

分析 Hashset 底层是 HashMap,HashMap 底层是(数组+链表+红黑树

(1)HashSet 底层是 HashMap

(2)添加一个元素时,先得到hash值-会转成->索引值

(3)找到存储数据表 table,看这个索引位置是否已经存放的有元素

(4)如果没有,直接加入

(5)如果有,调用 equals 比较,如果相同,就放弃添加,如果不相同,则添加到最后

(6)在 Java8 中,如果一条链表的元素个数超过 TREEIFY_THRESHOLD(默认是8),并且 table 的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)

红黑树机制

(1)HashSet 底层是 HashMap,第一次添加时,table 数组扩容到16,临界值(threshold)是16,加载因子(loadFactor)是0.75=12
(2)如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值就是32*0.75=24,依次类推
(3)在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64)就会进行树化(红黑树),否则仍然采用数组扩容机制

public class HashMap_<K, V> {

    transient Node<K, V>[] table;

    transient int modCount;

    transient int size;

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K, V>[] tab;
        Node<K, V> p;
        int n, i;

        // 属性table为null或table的长度为0,就扩容
        if ((tab = table) == null || (n = tab.length) == 0) {
            n = (tab = resize()).length;
        }
        // 如果tab[i]为null,表示没有存放元素,就创建节点并赋值给tab[i]
        if ((p = tab[i = (n - 1) & hash]) == null) {
            tab[i] = newNode(hash, key, value, null);
        } else {
            Node<K, V> e;
            K k;

            // p 和添加元素的hash值相同 并且 (key相同或equals相同),p赋值给e
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k)))) {
                e = p;

            }
            // 链表循环比较
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        break;
                    }
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k)))) {
                        break;
                    }
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null) {
                    e.value = value;
                }
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold) {
            resize();
        }
        return null;
    }

    int threshold;

    final float loadFactor = DEFAULT_LOAD_FACTOR;

    static final int MAXIMUM_CAPACITY = 1 << 30;

    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16
    // 加载因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    final Node<K, V>[] resize() {
        Node<K, V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap > 0) {
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            } else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                    oldCap >= DEFAULT_INITIAL_CAPACITY) {
                newThr = oldThr << 1; // double threshold
            }
        } else if (oldThr > 0) {
            newCap = oldThr;
        } else {
            // 扩容
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        if (newThr == 0) {
            float ft = (float) newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?
                    (int) ft : Integer.MAX_VALUE);
        }
        threshold = newThr;

        // 初始化数组,并赋值给属性table
        Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];
        table = newTab;

        return newTab;
    }

    Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {
        return new Node<>(hash, key, value, next);
    }

    static class Node<K, V> {
        final int hash;
        final K key;
        V value;
        Node<K, V> next;

        Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }
}

三、LinkedHashset(P528)

1. LinkedHashSet 的说明

(1)LinkedHashSet 是 Hashset 的子类

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

(3)LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的


(4)LinkedHashset 不允许添重复元素

(1)在 LinkedHashSet 中维护了一个 hash 表和双向链表(LinkedHashSet 有 head 和 tail)

(2)每一个节点有 pre 和 next 属性,这样可以形成双向链表

(3)在添加一个元素时,先求hash值,在求索引,确定该元素在 hashtable 的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加【原则和 hashset 一样】)

(4)遍历 LinkedHashSet 也能确保插入顺序和遍历顺序一致

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

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

相关文章

SpringBoot中MQ使用

本文记录学习在Spring Boot中使用MQ。一 什么是MQMQ全称&#xff08;Message Queue&#xff09;又名消息队列&#xff0c;是一种异步通讯的中间件。它的作用类似于邮局&#xff0c;发信人(生产者)只需要将信(消息)交给邮局&#xff0c;然后由邮局再将信(消息)发送给具体的接收者…

博途1200PLC/1500PLCMODBUS从站通信应用

博途PLC作为MODBUS主站通信请参看下面的文章链接: 博途PLC 1200/1500PLC MODBUS-RTU通讯优化(状态机编程)_博途plc modbus-rtu通信优化_RXXW_Dor的博客-CSDN博客博途PLC 1200/1500PLC MODBUS-RTU通讯_RXXW_Dor的博客-CSDN博客_博图modbus通讯1、1200PLC的modbus通讯,可以参看…

HTTP协议(1)

1)HTTP协议是倾向于相遇业务层次上面的一种协议&#xff0c;传输层协议主要考虑的是端对端之间的一个传输过程&#xff0c;TCP重点进行关注的是可靠传输&#xff1b;咱们的HTTP/1&#xff0c;HTTP/2是基于TCP的&#xff0c;但是咱们的HTTP/3是基于UDP的&#xff0c;但是当下的互…

实战动态代理

代理模式介绍代理模式有点像老大和小弟&#xff0c;也有点像分销商。主要解决的是问题是为某些资源的访问、对象的类的易用操作上提供方便使用的代理服务。而这种设计思想的模式经常会出现在我们的系统中&#xff0c;或者你用到过的组件中&#xff0c;它们都提供给你一种非常简…

【CVPR 2018】PU-Net: Point Cloud Upsampling Network

文章目录PU-Net: Point Cloud Upsampling Network网络架构训练数据生成点特征嵌入Feature ExpansionCfoordinate Reconstruction端到端训练Joint Loss FunctionPU-Net: Point Cloud Upsampling Network 网络架构 PU-Net有四个组件&#xff1a;patch extraction, point feature…

「自定义类型」C语言中的构造数据类型如结构,联合,枚举

​​​​​​​&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680;目录 &#x1f430;结构 &#x1f3e1; 前言 &#x1f338;数据类型的定义 &…

SpringBoot动态导出word文档(完美实整教程 复制即可使用,不能实现你找我)

背景 最近有一个需求是需要动态导出合同、订单等信息&#xff0c;导出一个word文档供客户进行下载查看。 需要导出的word文件&#xff0c;主要可以分为两种类型。 导出固定内容和图片的word文档导出表格内容不固定的word文档 经过对比工具&#xff0c;我实践过两种实现方式…

一文细说引导内存分配器

一、引导内存分配器 1.引导内存分配器的作用 因为内核里面有很多内存结构体&#xff0c;不可能在静态编译阶段就静态初始化所有的这些内存结构体。另外&#xff0c;在系统启动过程中&#xff0c;系统启动后的物理内存分配器本身也需要初始化&#xff0c;如伙伴分配器&#xff…

OD笔试题-空汽水瓶可以换汽水

/*** 某商店规定&#xff1a;三个空汽水瓶可以换一瓶汽水&#xff0c;允许向老板借空汽水瓶&#xff08;但是必须要归还&#xff09;。* 小张手上有n个空汽水瓶&#xff0c;她想知道自己最多可以喝到多少瓶汽水。* 数据范围&#xff1a;输入的正整数满足 1≤n≤100* <p>*…

springboot 多环境配置yml

创建多个配置文件 创建文件时注意&#xff0c;一定是 application-文件名称.yml 这种格式 application.yml #主配置文件 application-dev.yml #开发环境的配置 application-prod.yml #生产环境的配置application-prod.yml # 生产环境端口为90 server:port: 90applica…

Python实现将一段话txt生成字幕srt文件

Python实现将一段话txt生成字幕srt文件 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 一、为什么要将txt转换成字幕 1.1方便到剪辑软件剪辑 有时获取到一段文本&#xff0c;想要直…

点分治学习笔记

有时候我们会碰到一些树上的路径问题&#xff0c;如果需要处理的规模很大的话&#xff0c;这时候点分治是一个很好的工具&#xff0c;往往可以在O(nlogn)的复杂度内完成操作&#xff0c;一般用于离线处理问题 前置芝士 树的重心&#xff1a;最大子树的值最小的点叫做重心。 …

【手撕面试题】HTML+CSS(高频知识点二)

目录 面试官&#xff1a;页面导入样式时&#xff0c;使用 link 和 import 有什么区别&#xff1f; 面试官&#xff1a;简要说说 title与h1的区别、b与strong的区别、i与em的区别&#xff1f; 面试官&#xff1a;img标签的title和alt有什么区别&#xff1f; 面试官&#xff…

给特别规则FeignClient增加统一的RequestInterceptor

需求背景&#xff1a; 在微服务横行天下的今天&#xff0c;Spring Cloud OpenFeign 早就成了我们服务间调度的主要远程调用手段。 在Feign进行远程调度的时候&#xff0c;难免会做一些心跳&#xff0c;权限的校验&#xff0c;来保证调度过程的相对安全。 但对于外部系统来说…

Unity 之 Addressable可寻址系统 -- 资源远程加载 | 资源预下载 -- 进阶(三)

可寻址系统远程加载 -- 资源预下载 -- 进阶&#xff08;三&#xff09;一&#xff0c;Unity 云资源分发 -- 使用介绍1.1 CCD 的介绍1.2 后台准备工作二&#xff0c;CDD的使用2.1 CCD可视化界面的使用2.2 CDD命令行界面使用2.2.1 准备工作2.2.2 CLI 用法三&#xff0c;AA CCD资…

Java中的快速排序

快速排序递归版本挖坑法Hoare法优化非递归相信即使大家并不知道快速排序究竟是个啥,但也一定听说过快排,今天我来给兄弟们讲讲快速排序!递归版本 快速排序的思想就是找基准,就比如我们以数组中的第一个数字12为基准,我们从最后往前面找,如果找到一个比12小的数字就用它覆盖12,但…

Linux—InstallOS-RedHat9.1

下载https://developers.redhat.com/products/rhel/download 需注册账号。安装正常安装就行。安装注意事项&#xff1a;(1)Software SelectionCentOS的摘录过来&#xff0c;通用。最小安装&#xff08;Minimal Install&#xff09;这个选项只提供运行CentOS 的基本软件包。最小…

Python学习-----起步4(列表元素的添加,删除,修改,查询,获取长度)

目录 前言&#xff1a; 列表元素的添加&#xff08;或者叫写入&#xff09; 1.append&#xff08;&#xff09;函数 2.extend&#xff08;&#xff09;函数 3.insert()函数 列表元素的删除 1.remove() 函数 2. pop() 函数 3.clear&#xff08;&#xff09;函数 4.del …

公司40岁的程序員到底在写什么代码

去年在前公司玩了一年&#xff08;基本兩三個月一個需求&#xff09;&#xff0c;除了日常維護就一些特別簡單的功能開發&#xff0c;到年底也沒見到公司黃&#xff08;國企背景&#xff09;&#xff0c;沒辦法只好裸辭&#xff0c;現在這個公司各方面还不错&#xff0c;但是令…

Cookie、Session、Token、JWT只看这一篇文章就够了

什么是认证&#xff08;Authentication&#xff09; 通俗地讲就是验证当前用户的身份&#xff0c;证明“你是你自己”&#xff08;比如&#xff1a;你每天上下班打卡&#xff0c;都需要通过指纹打卡&#xff0c;当你的指纹和系统里录入的指纹相匹配时&#xff0c;就打卡成功&a…