day10-Set集合

news2024/11/24 15:29:14

1.Set

那接下来我们来看Collection单列集合体系的第二部分 Set集合。

在这里插入图片描述

1.1 Set集合概述和特点

Set集合特点

1.可以去除重复

2.存取顺序不一致

3.没有带索引的方法,所以不能使用普通fori循环遍历,也不能通过索引来获取,删除Set集合里面的元素

Set集合练习

存储字符串并遍历

1.2 数据结构-树

在这里插入图片描述

1.3 红黑树

平衡二叉B树

每一个节点可以是红或者黑

红黑树不是高度平衡的,它的平衡是通过“自己的红黑规则"进行实现的

在这里插入图片描述

2.HashSet

2.1 HashSet集合概述和特点

HashSet集合特点

1.底层数据结构是哈希表

2.存取无序

3.无索引 所以不能使用普通for循环遍历

4.不能存在重复值

HashSet集合练习

存储字符串并遍历

扩展:什么是哈希表?

什么是哈希表?
哈希表是一种以键值key存储数据value的结构,以key作为标识值存储value值;只要输入待查找的key,即可获取其对应的value值
 public HashSet() {
        map = new HashMap<>();
    }

163/16

2.2 哈希值

在了解哈希表之前我们要先了解哈希值。

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一个方法可以获取对象的哈希值

public int hashCode():返回对象的哈希码值

在存入set集合的时候会调用hash算法

**哈希算法 **

根据元素的哈希值跟数组的长度求余计算出存入的位置

对象的哈希值特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的

默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

我们在之前重写过Object的equals方法

Java中规定:
(1)如果两个对象通过equals方法比较是相等的,那么它们的hashCode方法结果值也是相等的。
(2)如果两个对象通过equals方法比较是不相等的,那么它们的hashCode方法结果值不一定不相等。

代码展示:

public class Animal {
    private String name;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Animal)) return false;
        Animal animal = (Animal) o;
        return Objects.equals(name, animal.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

public class Test {
    public static void main(String[] args) {
        String s1 = "山东高合";
        String s2 = "山东高合";
        String s3 = "山东高合科技";
        String s4 = "山东高合科技";
        System.out.println(s1.hashCode());//725470523
        System.out.println(s2.hashCode());//725470523
        System.out.println(s3.hashCode());//1393462602
        System.out.println(s4.hashCode());//1393462602
        
        Animal a = new Animal();
        Animal b = new Animal();
        System.out.println(a.hashCode());//31
        System.out.println(b.hashCode());//31
        System.out.println(a.equals(b));//true
    }
}

哈希的常见应用场景:

在日常运营活动中,我们活动开发经常遇到的应用场景是
1.安全加密、
2.唯一标识、
3.数据校验。
4.散列函数
5.负载均衡

常见数据结构之哈希表

哈希表JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组

JDK8以后,在长度比较长的时候,底层实现了优化,采用的是数组+二叉树

HashSet1.7版本原理

164/16

HashSet<String> hm = new HashSet<>();

//是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap

在这里插入图片描述

创建一个默认长度16,默认负载因子为0.75的数组,数组名table
根据元素的哈希值跟数组的长度计算出应存入的位置
判断当前位置是否为null,如果是null直接存入
如果位置不为null,表示有元素,则调用equals方法比较属性值
如果一样,则不存,如果不一样,则存入数组,老元素挂在新元素下面

负载因子是在自动增加其哈希表容量之前允许哈希表获得的满度的度量

当哈希表中的条目数超过负载因子和当前容量的乘积时,哈希表将被重新哈希
(即,内部数据结构将被重建),因此哈希表的存储桶数大约为两倍。

通常,默认负载因子(.75)在时间和空间成本之间提供了一个很好的折中方案。
较高的值会减少空间开销,但会增加查找成本(在HashMap类的大多数操作中都得到体现,包括get和put)。设置映射表的初始容量时,应考虑映射中的预期条目数及其负载因子,以最大程度地减少重新哈希操作的数量。如果初始容量大于最大条目数除以负载因子,则将不会进行任何哈希操作。

HashSet1.8 版本原理

底层结构:哈希表。(数组、链表、红黑树的结合体)。
当挂在下面的元素过多,那么不利于查询,所以在JDK8以后,
当链表长度超过 8 的时候,自动转换为红黑树。
存储流程不变。

转为红黑树之后排序规则:通过红黑的的规则进行对哈希值的比较对红黑树的内容进行排序

2.3 并发工具类

创建一个默认长度16,默认负载因子为0.75的数组,数组名table

根据元素的哈希值跟数组的长度计算出应存入的位置

判断当前位置是否为null,如果是null直接存入
如果位置不为null,表示有元素,则调用equals方法比较属性值

如果一样,则不存,如果不一样,则存入数组,新元素挂在老元素下面

当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍

利用HashSet存储自定义元素,必须重写hashCode和equals方法

2.4 案例:HashSet集合存储学生对象并遍历

**需求:**创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象

思路:

1.定义学生类

2.创建HashSet集合对象

3.创建学生对象

4.把学生添加到集合

5.遍历集合(增强for)

6.在学生类中重写两个方法hashCode()和equals()自动生成即可

3.TreeSet

3.1 TreeSet集合概述和特点

TreeSet集合特点

1.元素唯一

2.无索引

3.可以将元素按照规则进行排序

TreeSet集合练习

存储Integer类型的整数,并遍历

存储学生对象,并遍历

 		TreeSet<Student> t1 = new TreeSet<>();
        t1.add(new Student("一号",16));
        t1.add(new Student("二号",18));
        t1.add(new Student("三号",10));
        t1.add(new Student("四号",15));
        System.out.println(t1);
//Exception in thread "main" java.lang.ClassCastException: com.itgaohe.lesssion14.Student cannot be cast to java.lang.Comparable 报错!!!必须指定排序规则!!

想要使用TreeSet,需要制定排序规则

3.2 自然排序Comparable的使用

1.使用空参构造创建TreeSet集合

2.自定义的Student类实现Comparable接口

3.重写里面的compareTo​方法

TreeSet集合练习

改写存储学生对象的案例,并按照年龄从小到大排列

Student

public class Student implements Comparable<Student> {
    private String name;
    private int age;
    
    ...getter/setter
    
       // 方式一:类自定义比较规则
    @Override
    public int compareTo(Student o) {
        return this.age - o.getAge();
    }
}

再次运行

3.3 自然排序简单原理图

1.如果返回值为负数,表示当前存入的元素是较小值,存左边
2.如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
3.如果返回值为正数,表示当前存入的元素是较大值,存右边

在这里插入图片描述

3.4 案例:按照年龄排序

需求:改写刚刚的学生案例;

要求:按照年龄从小到大排,如果年龄一样,则按照姓名首字母排序
如果姓名和年龄一样,才认为是同一个学生对象,不存入。

代码展示:

Student

// 方式一:类自定义比较规则 
    @Override
    public int compareTo(Student o) {
        //按照年龄从小到大排
        int r = this.age-o.age;
        //年龄一样 咱要首字母存入
        r = (r==0?this.name.compareTo(o.getName()):r);
        return r;
    }
		TreeSet<Student> t1 = new TreeSet<>();
        t1.add(new Student("amy",15));
        t1.add(new Student("betty",15));
        t1.add(new Student("carrt",15));
        t1.add(new Student("dog",15));
        t1.add(new Student("green",15));
        t1.add(new Student("hs",16));
        t1.add(new Student("icon",17));
        t1.add(new Student("efls",15));
        t1.add(new Student("fer",15));
        t1.add(new Student("fery4",15));

打印结果

[Student{name='amy', age=15}, Student{name='betty', age=15}, Student{name='carrt', age=15}, Student{name='dog', age=15}, Student{name='efls', age=15}, Student{name='fer', age=15}, Student{name='fery4', age=15}, Student{name='green', age=15}, Student{name='hs', age=16}, Student{name='icon', age=17}]

3.5 比较器排序Comparator的使用

1.TreeSet的带参构造方法使用的是比较器排序对元素进行排序的
2.比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare​(T o1,T o2)方法

//o1表示现在要存入的那个元素
 //o2表示已经存入到集合中的元素

3.重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

练习:

需求:用第二种方式实现下面的需求;

要求:自定义Teacher老师类,属性为姓名和年龄

​ 请按照年龄排序,如果年龄一样,

​ 则按照姓名进行排序。姓名都使用英文字母表示。

代码展示

Teacher


测试:

public static void main(String[] args) {
    TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
        @Override
        public int compare(Teacher t1, Teacher t2) {

            int age = t1.getAge() - t2.getAge();
            age = (age == 0 ? t1.getName().compareTo(t2.getName()) : age);
            return age;
        }
    });
    ts.add(new Teacher("z", 18));
    ts.add(new Teacher("s", 18));
    ts.add(new Teacher("z", 16));
    ts.add(new Teacher("a", 18));
    System.out.println(ts);
}

3.6 两种比较方式小结

1.自然排序:自定义类实现Comparable接口,重写compareTo​方法,根据返回值进行排序。
2.比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。
3.在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,使用比较器排序

两种方式中,关于返回值的规则:
1.如果返回值为负数,表示当前存入的元素是较小值,存左边
2.如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
3.如果返回值为正数,表示当前存入的元素是较大值,存右边

3.7 案例:按照字符串长短排序

需求:请自行选择比较器排序和自然排序两种方式;
要求:存入四个字符串, “c”, “ab”, “df”, “qwer”
按照长度排序,如果一样长则按照首字母排序

 public static void main(String[] args) {
        Set<String> set = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int r = o1.length() - o2.length();
                r =  r == 0? o1.compareTo(o2):r;
                return r;
            }
        });
        set.add("c");
        set.add("ab");
        set.add("df");
        set.add("qwer");
        System.out.println(set);
    }

3.8 案例:成绩排序

需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),
按照总分从高到低输出到控制台

思路:

1.定义学生类

2.创建TreeSet集合对象,通过比较器排序进行排序

3.创建学生对象

4.把学生对象添加到集合

5.遍历集合

代码:

public class Student {
    private int score;

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public Student(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "score=" + score +
                '}';
    }
}

测试:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    Student student = null;
    Set<Student> set = new TreeSet<>(new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            return o1.getScore()-o2.getScore();
        }
    });
    for (int i = 0; i < 3; i++) {
        System.out.println("请输入成绩:");
        String score = sc.next();
        int age = Integer.parseInt(score);
        student = new Student(age);
        set.add(student);
    }
    System.out.println(set);
}

3.9 总结

在这里插入图片描述

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

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

相关文章

WebSocket 详解加入门实操理解加深

WebSocket 介绍 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c; 并进行双向数据传输。 HTTP协议和WebSocket协议对比&#xff1a; HTTP是短连接…

基于SpringBoot的竹宣非遗宣传网站

摘要 随着互联网的普及和数字化时代的到来&#xff0c;竹编等非物质文化遗产的保护与传承面临新的机遇和挑战。该研究旨在使用SpringBoot后端框架与Vue前端框架&#xff0c;构建一个竹编非遗宣传网站&#xff0c;通过丰富的展示形式和交互体验&#xff0c;提升公众对竹编这一非…

怎么解决端口被占用

目录 一、引言 二、解决方法 一、引言 最近用vscode写网页&#xff0c;老是遇见端口被占用&#xff0c;报错如下&#xff1a; listen tcp :8080: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted. 二、解决方法 1.换…

OpenHarmony 实战开发 - 如何在源码中编译复杂应用(4.0-Release)

文档环境 开发环境&#xff1a;Windows 11 编译环境&#xff1a;Ubuntu 22.04 开发板型号&#xff1a;DAYU 200&#xff08;RK3568&#xff09; 系统版本&#xff1a;OpenHarmony-4.0-Release 功能简介 在 OpenHarmony 系统中预安装应用的 hap 包会随系统编译打包到镜像中&a…

数字水印 | 基于小波变换的数字水印技术

&#x1f34d;原文&#xff1a; 基于小波变换的数字水印技术 &#x1f34d;写在前面&#xff1a; 本文属搬运博客&#xff0c;自己留存学习。 正文 小波变换 把一个信号分解成由基本小波经过移位和缩放后的一系列小波&#xff0c;它是一种 “时间——尺度” 信号的多分辨率分…

# 从浅入深 学习 SpringCloud 微服务架构(十七)--Spring Cloud config(1)

从浅入深 学习 SpringCloud 微服务架构&#xff08;十七&#xff09;–Spring Cloud config&#xff08;1&#xff09; 一、配置中心的 概述 1、配置中心概述 对于传统的单体应用而言&#xff0c;常使用配置文件来管理所有配置&#xff0c;比如 SpringBoot 的 application.y…

面试中算法(金矿)

有一位国王拥有5座金矿&#xff0c;每座金矿的黄金储量不同&#xff0c;需要参与挖掘的工人人数也不同。 例如&#xff0c;有的金矿储量是5ookg黄金&#xff0c;需要5个工人来挖掘;有的金矿储量是2ookg黄金&#xff0c;需要3个工人来挖掘...... 如果参与挖矿的工人的总数是10。…

HTTP 连接详解

概述 世界上几乎所有的 HTTP 通信都是由 TCP/IP 承载的&#xff0c;客户端可以打开一条TCP/IP连接&#xff0c;连接到任何地方的服务器。一旦连接建立&#xff0c;客户端和服务器之间交换的报文就永远不会丢失、受损或失序 TCP&#xff08;Transmission Control Protocol&…

【大数据】HDFS、HBase操作教程(含指令和JAVA API)

目录 1.前言 2.HDFS 2.1.指令操作 2.2.JAVA API 3.HBase 3.1.指令操作 3.2.JAVA API 1.前言 本文是作者大数据专栏系列的其中一篇&#xff0c;前文中已经详细聊过分布式文件系统HDFS和分布式数据库HBase了&#xff0c;本文将会是它们的实操讲解。 HDFS相关前文&#x…

商家转账到零钱怎么开通?一步步教你玩转微信营销新利器

在数字化营销日新月异的今天&#xff0c;微信支付凭借其便捷、安全的特点&#xff0c;成为了商家不可或缺的支付工具。而其中的“商家转账到零钱”功能&#xff0c;更是为商家提供了一个全新的营销利器。今天&#xff0c;我们就来详细解读一下如何开通这一功能&#xff08;我处…

强化学习在一致性模型中的应用与实验验证

在人工智能领域&#xff0c;文本到图像的生成任务一直是研究的热点。近年来&#xff0c;扩散模型和一致性模型因其在图像生成中的卓越性能而受到广泛关注。然而&#xff0c;这些模型在生成速度和微调灵活性上存在局限。为了解决这些问题&#xff0c;康奈尔大学的研究团队提出了…

从0开始学python(七)

目录 前言 1 break、continue和pass函数 1.1 break 1.2 continue 1.3 pass 2、序列的索引及切片操作 2.1字符串的索引和切片 2.1.1 字符串索引 2.1.2 字符串切片 总结 前言 上一篇文章我们介绍了python中的循环结构&#xff0c;包括for和while的使用。本章接着往下讲。…

springboot+layuimini实现树形表格

树形表格实现增删改查 这里写目录标题 效果图前端页面代码前端插件后端代码controllerserviceserviceImpl 实现类Entitymapperxml mybatis代码数据表 效果图 前端页面代码 <!DOCTYPE html> <html lang"en" xmlns:th"http://www.thymeleaf.org"&g…

java项目之企业OA管理系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的企业OA管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 企业OA管理系统的主要使用…

CCPD车牌检测识别数据集

CCPD 是一个在开源免费的中国城市车牌识别数据集。 1. 介绍 CCPD (Chinese City Parking Dataset, ECCV)是中国城市车牌数据集&#xff0c;共有两个CCPD2019和CCPD2020 数据集&#xff0c;总数据量约35W左右&#xff0c;可用于车牌检测和识别模型算法开发。 CCPD 发表的论文:…

体验GM CHM Reader Pro,享受高效阅读

还在为CHM文档的阅读而烦恼吗&#xff1f;试试GM CHM Reader Pro for Mac吧&#xff01;它拥有强大的功能和出色的性能&#xff0c;能够让你轻松打开和阅读CHM文件&#xff0c;享受高效、舒适的阅读体验。无论是学习、工作还是娱乐&#xff0c;GM CHM Reader Pro都能成为你的得…

(java)websocket服务的两种实现方式

1.基于java注解实现websocket服务器端 1.1需要的类 1.1.1服务终端类 用java注解来监听连接ServerEndpoint、连接成功OnOpen、连接失败OnClose、收到消息等状态OnMessage 1.1.2配置类 把spring中的ServerEndpointExporter对象注入进来 2.1代码示例 2.1.1 maven配置 <…

字节码基础

基本概念 java中的字节码&#xff0c;英文bytecode。是java代码编译后的中间代码格式。JVM需要读取并解析字节码才能执行相应的任务。java字节码是JVM的指令集。JVM加载字节码格式的class文件。校验之后通过JIT编译器转换成本机机器代码执行。 java字节码简介 1、java byteco…

MySQL 身份认证漏洞 CVE-2012-2122

漏洞影响版本 MariaDB versions from 5.1.62, 5.2.12, 5.3.6, 5.5.23 are not.MySQL versions from 5.1.63, 5.5.24, 5.6.6 are not.演示 开启靶场 进入漏洞目录 cd /root/vulhub/mysql/CVE-2012-2122开启漏洞靶场 docker-compose up -d攻击 直接 运行 这个命令 for i i…

基于SSM+Vue的物流管理系统

运行截图 获取方式 Gitee仓库