java进阶—一篇文章搞懂set 集合 及其底层实现

news2024/12/24 3:04:56

上节我们知道了List 下的两大 子类 ArrayList 跟 linkedList

ArrayList 数组结构 查询快,增删慢

LinkedList 链表结构 查询慢,增删快

来看看我们今天的主角: Set

Set 是 不可重复的,其底下也有两大子接口:

HashSet:无序且唯一

TreeSet :有序且唯一

先礼后兵,我们直接来看操作set集合有哪些方法,其实与list 的方法一样,两个子类都是,我们拿最常用的HashSet为例子

  • 添加(add)
  Set<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("资讯");


        for (String item : hashSet) {
            System.out.println(item);
        }

在这里插入图片描述

  • 移除(remove)
Set<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("公众号搜索:“java资讯");


        hashSet.remove("公众号搜索:“java资讯");

        for (String item : hashSet) {
            System.out.println(item);
        }

在这里插入图片描述

  • 判断集合中是否有该元素(contains)

        Set<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("资讯");

        boolean flag = hashSet.contains("java");
        System.out.println(flag);

在这里插入图片描述

  • 获取集合的大小(size)
Set<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("资讯");

        int size = hashSet.size();
        System.out.println(size);

在这里插入图片描述

  • 判断集合是否为空(isEmpty)
Set<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("资讯");

        boolean flag = hashSet.isEmpty();
        System.out.println(flag);

在这里插入图片描述

接下来我们一起看探索set 三个子类的底层 (面试会问,需了解,建议收藏,留个印象)

  • HashSet (无序且唯一)

HashSet 是Set 接口中最常见的实现类,底层数据结构是哈希表

什么是哈希表?

用一个例子来说明:

有这么24个篮球,编号分别为1-24,需要将篮球分成六组应该怎么分

这还不简单 :

编号 1 -4 第一组 5-8 第二组 9-12 第三组

编号 13-16 第四组 17-20 第五组 21-24 第六组

那如果我要找 16 号篮球球在哪个组呢? 这数据才24, 要找到也方便,要是数据量变大,成百上千,分成多个组,要快速找到想要的编号在哪个组,就显得困难了

这时候就推出了哈希,进行散列

具体实现:

分成6组

将 编号除 6 余数为0 的为 第零组:6、12、18、24

将 编号除 6 余数为1 的为 第一组:1、7、13、19

将 编号除 6 余数为2 的为 第二组:2、8、14、20

将 编号除 6 余数为3 的为 第三组:3、9、15、21

将 编号除 6 余数为4 的为 第四组:4、10、16、22

将 编号除 6 余数为5 的为 第五组:5、11、17、23

这要我们要找一个编号就很方便,比如找16,16%6 =4 16 在第四组 ,这种方式就是高效的散列,我们称之为Hash

来看看哈希的运行图解,还是以上述篮球分组为例:

在这里插入图片描述
这里有几个概念:

key:就是编号

索引:数组的下标,可以快速定位,检索,我们分组的序号

哈希函数:将编号映射到索引上,采用的是取余方法 % 余数代表数组下标

哈希桶:保存索引的值的数组或链表,每个索引相同的元素以链表形式连接

通过上述,可以知道,这个存放数据的散列表就是我们说的哈希表

现在我们来看看 HashSet 的无序且唯一这个特性,通过对比代码呈现

 public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("王五");

        for (String item : list) {
            System.out.println(item);
        }
        System.out.println("-------------------------");


        Set<String> hashSet = new HashSet<>();
        hashSet.add("张三");
        hashSet.add("李四");
        hashSet.add("王五");
        hashSet.add("王五");


        for (String item : hashSet) {
            System.out.println(item);
        }
}

输出结果

在这里插入图片描述
可以看出,List 是有序的,谁先添加,谁先输出,而set没有按照顺序来,

并且list可以存储重复的数据,set会自动去重

  • TreeSet (有序,唯一)

TreeSet 底层实现是红黑树,默认排序为从小到大。是有序的,

注意:这里的有序并不是list 的 先进先出的有序,他会进行自然排序 ,对数据进行排序后输出

   Set<Integer> treeSet = new TreeSet<>();
        treeSet.add(88);
        treeSet.add(66);
        treeSet.add(10);
        treeSet.add(3);
        treeSet.add(6);
        for (Integer item : treeSet) {
            System.out.println(item);
        }

在这里插入图片描述

红黑树,这边有一个演示地址,复制到浏览器进行打开,https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

在这里插入图片描述
第一次存储数据没有树根就创建树根,然后这个元素 就是树根

第二次存储元素先跟节点比较,

          当存储元素的值大于根节点的值,将元素存储在右边

          当存储元素的值小于根节点的值,将元素存储在左边

          当存储元素的值等于根节点的值,那就不存了,因为是唯一的 

TreeSet 有两个排序机制,体现在它的构造器上,分为:自然排序,比较器排序

可以看看他的构造器:

//构造一个新的空 自然顺序进行排序。
TreeSet()
// 指定比较器进行排序。
TreeSet(Comparator<? super E> comparator)

自然排序用的是Comparable 接口有一个 compareTo(Object o) 方法,两个元素为0 相同,不再重复存储,返回正数 表明 前数据 大于 后数据 ,负数则反之

比较器排序 用的是 compare(Object o1,Object o2),返回结果跟判断原则跟compareTo 一样

主要区别,构造上也能看到,一个对应空参创建TreeSet 一个对应有参创建TreeSet

扩展

linkedHashSet (这个是HashSet的子节点),它是有序且唯一,底层结构为链表加哈希表,链表保证了元素有序(这个有序是顺序,不是排序的大小),有序是因为它在节点处增加了前和后 (属性维护节点的前后添加顺序)

   Set<Integer> treeSet = new LinkedHashSet<>();
        treeSet.add(88);
        treeSet.add(66);
        treeSet.add(10);
        treeSet.add(3);
        treeSet.add(6);
        for (Integer item : treeSet) {
            System.out.println(item);
        }

在这里插入图片描述
在这里插入图片描述
java进阶—List

Java中的集合

二维数组详细解析

Java中的注释

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

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

相关文章

我用Python轻松玩转ChatGPT的聊天机器人和AI画画

ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型&#xff0c;一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;甚…

分享112个图片切换,总有一款适合您

分享112个图片切换&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 112个图片切换下载链接&#xff1a;https://pan.baidu.com/s/1Q6DzF8wIQ9rXwFjydI6_kw?pwdktxr 提取码&#xff1a;kt…

Leetcode.1145 二叉树着色游戏

题目链接 Leetcode.1145 二叉树着色游戏 Rating &#xff1a; 1741 题目描述 有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中&#xff0c;给出二叉树的根节点 root&#xff0c;树上总共有 n个节点&#xff0c;且 n为奇数&#xff0c;其中每个节点上的值从 1到 n各不相…

关于“智能出价“的一些探索和实践

背景在移动数字广告营销的整个链路中&#xff0c;主要有三个主体&#xff0c;分别是媒体、adx和dsp.对于一个adx系统&#xff0c;主要有两个功能&#xff0c;分别是&#xff1a;向下对接媒体&#xff1a;汇聚下游的媒体广告流量向上对接dsp(广告主)&#xff1a;将媒体流量卖给上…

【C语言】看了这篇文章,如果你还不会文件操作的话,我把这篇文章给吃了(doge)

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

MyBatis注解CRUD执行流程剖析

MyBatis Study Notes Day03 结果映射ResultMap 引入resultMap–MyBatis中最强大的元素 数据库字段名&#xff1a;&#xff1a; 实体类字段名&#xff1a; public class User {private int id;private String name;private String password;如上所示&#xff0c;当sql的字段…

动态规划详解(1)——基础概念

动态规划是数学、编程中一个重要的算法动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;是运筹学的一个分支&#xff0c;是求解决策过程最优化的过程。20世纪50年代初&#xff0c;美国数学家贝尔曼&#xff08;R.Bellman&#xff09;等人在研究多阶段决策过…

Java——根据身高重建队列

题目链接 leetcode在线oj题——根据身高重建队列 题目描述 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个…

Spring AOP表达式(execution)规则——排除切点的应用

背景 需要项目原切面的基础上排除一些类中方法。 本篇文章主要介绍了SpringBoot AOP Pointcut切入点表达式&#xff0c;以及如何排除某些类中的方法的方式。 execution(* com.winup.web.controller..*.*(..)) 参数说明 符号含义execution&#xff08;&#xff09;表达式的…

【C++之类和对象】默认成员函数

目录前言一、默认成员函数二、构造函数三、析构函数四、拷贝构造函数五、赋值运算符重载前言 前面我们学习了一些类和对象的基本知识&#xff0c;知道了什么是类&#xff0c;类中包括什么东西&#xff0c;以及能够使用一个类来实例化对象&#xff0c;并且会计算类对象的大小。这…

Java Collection 接口下的 “ List 集合” 与 “ Set 集合 ”

Java Collection接口下的“ List 集合” 与 “ Set 集合 ” 每博一文案 一个人最好的底牌&#xff0c;就这两个字: 靠谱,是最高级的聪明。 师父说&#xff1a;人生一回&#xff0c;道义一场&#xff0c;你对人对事的态度&#xff0c;藏着你一生的福报。 千金难买好人缘&#x…

SpringBoot(三):日志文件

目录一、日志文件1.1 日志文件的作用1.2 Spring Boot内置了日志框架1.3 日志的格式说明1.4 自定义日志打印1.5 日志的持久化1.6 日志的级别1.6.1 日志级别有什么作用1.6.2 日志的级别划分1.6.3 日志级别的设置1.7 使用lombok输出日志1.7.1 lombok的原理1.7.2 lombok其他注解一、…

在JS文件中使用或扩展已有的vue文件

工作中遇到一个给现有项目增加一个超时重新登录的提醒框&#xff08;可在提醒框中直接登录本账户&#xff09;。 由于页面稍微复杂&#xff0c;本人又是脚手架一把梭过来的&#xff0c;对于直接使用 js 来完成一整个复杂还带逻辑的页面稍显吃力&#xff0c;所以决定先写一个 vu…

建模助手【有求必应】的正确打开方式

今天的话题主要想解除大家对[有求必应] 的一些误解。 因为在日常的反馈中用户似乎对于[提需求] 这玩意儿无论是从概念上还是动作上都很不 “熟悉”。 其实我们对软件认知的上限是一个软件功能的上限&#xff0c;产品以及行业的发展都要从打破固有认知开始。 期待更多的你们跳出…

《新华日报·科技周刊》聚焦蓝海彤翔与《流浪地球2》

瞄准世界科技前沿瞄准江苏科技创新瞄准日常科技生活《新华日报科技周刊》第203期聚焦《流浪地球2》中的大国重器其实就在我们身边重点报道了蓝海创意云渲染农场为《流浪地球2》提供了云计算渲染服务的重要成果“数字生命计划”就是元宇宙吗&#xff1f;电影中人类面临末日危机&…

0基础如何入门人工智能?

1.1 概念 根据维基百科的解释&#xff0c;人工智能是被机器展示的智力&#xff0c;与人类和其他动物的自然智能相反&#xff0c;在计算机科学中 AI 研究被定义为 “代理人软件程序”&#xff1a;任何能够感受周围环境并且能最大化它成功机会的设备。 1.2 重大事件 2016 年 3…

[Java]JavaWeb学习笔记(尚硅谷2020旧版)

文章目录&#x1f3c0; 视频及资料地址&#x1f3c0; XML⚽ XML 简介&#x1f3d0; xml 的作用⚽ XML 语法&#x1f3d0; 文档声明&#x1f3d0; 注释&#x1f3d0; 元素(标签)⚾ XML 命名规则⚾ xml 中的元素(标签)也分单双标签&#x1f3d0; xml 元素属性&#x1f3d0; 语法规…

PHP控制反转和依赖注入的理解(通俗易懂)

目录 1.IoC是什么 2.IoC能做什么 3.IoC和DI 4.IoC(控制反转) 5.DI(依赖注入) 6.我对IoC(控制反转)和DI(依赖注入)的理解 学习PHP各个框架的过程中&#xff0c;都会听过IoC(控制反转) 、DI(依赖注入)这两个概念&#xff0c;总觉得IoC 、DI这两个概念是模糊不清的&#xff…

WINSOFT JSEngine Delphi 6-D11

WINSOFT JSEngine Delphi 6-D11 WinsoftJSEngine被认为是一个海豚引擎&#xff0c;包括一个强大的JavaScript引擎。 Winsoft JSEngine的功能和特点&#xff1a; Microsoft ChakraCore JavaScript强大的引擎实用程序 支持32位和64位窗口 提供给海豚版本6 Eli 10.1和Lazarus 为产…

29岁,从餐饮到网络安全,大龄转行逆袭成功

大龄转行&#xff0c;一直在网络上备受讨论。 从学习能力、试错成本来考虑&#xff0c;转行一定是越早越好&#xff0c;而大龄转行风险极大。 大龄转行&#xff0c;固然并非一条绝路&#xff0c;苏老泉&#xff0c;二十七&#xff0c;始发愤&#xff0c;读书籍&#xff0c;有的…