第十四章 集合(Set)

一、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 底层是(数组+链表+红黑树)。

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赋值给eif (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 keyV 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;// 初始化数组,并赋值给属性tableNode<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;}}
}

(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,就会扩容到162=32,新的临界值就是320.75=24,依次类推。
(3)在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64)就会进行树化(红黑树),否则仍然采用数组扩容机制。

三、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.mzph.cn/news/536668.shtml

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

相关文章

数据结构:KMP算法

1.何为KMP算法 KMP算法是由Knuth、Morris和Pratt三位学者发明的&#xff0c;所以取了三位学者名字的首字母&#xff0c;叫作KMP算法。 2.KMP的用处 KMP主要用于字符串匹配的问题&#xff0c;主要思想是当出现字符串不匹配时&#xff0c;我们可以知道一部分之前已经匹配过的的文…

【期刊周报1】医学好刊(SCI/SSCI/EI),含Top,领域广,接收快!

为了向广大学者朋友提供更优质的选刊服务&#xff0c;提高选刊质量&#xff0c;我处现开设周报专栏&#xff0c;以罗列我处合作的优质期刊~ 本期&#xff0c;小编给大家推荐的是医学领域相关的热门期刊&#xff0c;接收领域广&#xff0c;无预警&#xff0c;且在最新检索目录内…

Python遥感影像深度学习指南(2)-在 PyTorch 中创建自定义数据集和加载器

在上一篇 文章中,我们Fast.ai 在卫星图像中检测云轮廓,检测物体轮廓被称为语义分割。虽然我们用几行代码就能达到 96% 的准确率,但该模型无法考虑数据集中提供的所有输入通道(红、绿、蓝和近红外)。问题在于,深度学习框架(如 Keras、Fast.ai 甚至 PyTorch)中的大多数语…

油烟净化器如何做到高效净化?科技力量,清新餐饮生活

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们。 油烟净化器的出现&#xff0c;为我们的餐饮生活注入了一抹清新的色彩。然而&#xff0c;它究竟是如何工作的&#xff1f;为何能…

【开题报告】基于SSM的健康饮食系统设计与实现

1.研究背景 如今&#xff0c;随着人们生活水平的提高和健康意识的增强&#xff0c;越来越多的人开始关注自己的饮食习惯&#xff0c;并希望通过合理的饮食来维持身体健康。然而&#xff0c;对于许多人来说&#xff0c;了解和选择合适的饮食方式并不容易。传统的饮食指导往往比…

【并发设计模式】聊聊Immutability模式利用不变性解决并发问题

上一篇文章&#xff0c;我们介绍了如何利用二阶段停止协议进行优雅停止线程和线程池&#xff0c;本篇介绍在并发编程中数据安全性&#xff0c;我们知道针对于数据的操作&#xff0c;读和写(添加、删除、修改), 在并发线程读写的时候&#xff0c;变量不加锁的情况下&#xff0c;…

redis哨兵+redis主从复制(在虚拟机centos的docker下)

1.安装docker Docker安装(CentOS)简单使用-CSDN博客 2.redis主从复制 redis主从复制(在虚拟机centos的docker下)-CSDN博客 3.编辑3个redis配置 cd /etc mkdir redis-sentinel cd redis-sentinel/ wget http://download.redis.io/redis-stable/sentinel.confcp sentinel.co…

ssh 免密登陆公钥设置失败分析调试

前景 看到这里肯定已经知道如何设置免密登陆。本文主要用于解决免密登陆设置失效问题。 ssh调试 目的 ssh设置了公钥仍然无法免密登陆; 需要调试 解决 通过systemctl status sshd的日志输出查看原因 步骤 打开调试 systemctl status sshd查看所在服务文件 $ sudo sys…

【并发编程篇】读锁readLock()和写锁writeLock()

文章目录 &#x1f6f8;情景引入⭐解决问题 readLock()和writeLock()都是ReadWriteLock接口中定义的方法&#xff0c;用于获取读锁和写锁。 readLock()方法返回一个读锁&#xff0c;允许多个线程同时获取该锁&#xff0c;以进行并发读取操作。如果当前已有一个写锁或其他线程正…

GIT具体配置步骤详解

GIT配置具体步骤如下 SDK 使用 Repo 工具管理&#xff0c;拉取 SDK 需要配置安装 Repo 工具。 Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workf…

装饰器模式和责任链模式区别

近期看了 mybatis 的源码&#xff0c;发现二级缓存这块用了装饰器模式将各个功能的缓存进行嵌套&#xff0c;源码上也是讲到使用了装饰器模式&#xff0c;但是看着跟责任链模式类似&#xff0c;本着搞清楚的想法&#xff0c;搜了很多资料&#xff0c;看了书籍《Head First 设计…

AI行业新趋势:百模大战中的变革与未来

AI行业新趋势&#xff1a;百模大战中的变革与未来 人工智能&#xff0c;这个曾经被视为科幻小说的情节&#xff0c;如今已经成为我们生活中的常态。从智能手机、自动驾驶汽车&#xff0c;到智能家居、医疗诊断&#xff0c;AI的应用已经深入到我们生活的各个角落。然而&#xf…

多维时序 | MATLAB实CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现CNN-BiGRU-Mutilhead-Attention卷积网络结合双向门控循环单元网络融合多头注意力机制多变量时间序列预测预测效果基本介…

ubuntu 22.04 安装mysql服务

完整内容&#xff1a; https://developer.aliyun.com/article/1260321 # 安装服务 sudo apt install mysql-server# 按向导设置root密码 sudo mysql_secure_installation# 使用设置的密码登录 sudo mysql -u root -p也可以使用工具登录&#xff0c;例如: navicat for mysql

协同工作php,PHPOA:灵活、高效、协同,让企业高效运转

原标题&#xff1a;PHPOA&#xff1a;灵活、高效、协同&#xff0c;让企业高效运转PHPOA系统作为一个管理系统&#xff0c;它的职责就是为企业高效运转而服务&#xff0c;以提高企业的办公效率为己任&#xff0c;减少不必要的资源浪费为责任。它保持高度的灵活性、高效性与协同…

ubuntu搭建php开发环境记录

2019独角兽企业重金招聘Python工程师标准>>> 这两天自己在阿里云上面买了一个ecs&#xff0c;系统选的是ubuntu16.04&#xff0c;第一件事就是先搭环境&#xff0c;这次准备使用lamp组合。 Apache安装 首先安装apache服务器&#xff0c;ubuntu下面使用apt-get来下载…

php datediff 函数,dateAdd与DateDiff函数的js代码

1、DateAdd函数&#xff1a;复制代码 代码示例:function DateAdd(interval,number,date){switch(interval.toLowerCase()){case "y": return new Date(date.setFullYear(date.getFullYear()number));case "m": return new Date(date.setMonth(date.getMont…

mysql索引为啥要选择B+树 (下)

有读者在 mysql索引为啥要选择B树 (上) 上篇文章中留言总结了选择 B 树的原因&#xff0c;大体上说对了&#xff0c;今天我们再一起来看看具体的原因。 索引为什么要保存在硬盘中首先要明白几个概念&#xff0c;服务器存储一般分内存和硬盘&#xff0c;内存的大小相对于硬盘来说…

des加解密java c#,C#编写DES加密、解密类

这个C#类封装的DES加密解密&#xff0c;可以使用默认秘钥进行加密、解密&#xff0c;也可以自定义秘钥进行加密、解密&#xff0c;调用简单方便。示例一&#xff1a;using System;using System.Security.Cryptography;using System.Text;namespace DotNet.Utilities{/// /// DE…

八年开发程序员浅析SpringBoot 之 Shiro 与 Redis 多级缓存问题

前言 来自不愿意透露姓名的小师弟的投稿。这篇主要讲了&#xff0c;项目中配置了多缓存遇到的坑&#xff0c;以及解决办法。 发现问题 在一次项目实践中有实现多级缓存其中有已经包括了 Shiro 的 Cache &#xff0c;本以为开启 redis 的缓存是一件很简单的事情只需要在启动类上…