40.java-单列集合Set(HashSet,LinkedHashSet,TreeSet)

news2024/11/26 11:59:37

Set集合

  • 1.Set集合特点
  • 2.Set集合实现类
  • 3. HashSet
    • 3.1 底层原理
      • 3.1.1 哈希表组成
      • 3.1.2 哈希值
      • 3.1.3 对象的哈希值特点
    • 3.2 数据添加元素的过程
    • 3.3 HashSet的三个问题
    • 3.4 实例:去除重复元素
  • 4. LinkedHashSet
  • 5. TreeSet
    • 5.1 特点
    • 5.2 集合默认规则
    • 5.3 例子
    • 5.4 两种比较规则
      • 5.4.1 默认排序
      • 5.4.2 比较器排序
    • 5.5. TreeSet对象排序练习
    • 5.6 TreeSet小结
      • 5.6.1 TreeSet集合的特点?
      • 5.6.2 TreeSet集合自定义排序规则有几种方式?
      • 5.6.3 方法返回值得特点
  • 6. 单列集合使用场景

1.Set集合特点

在这里插入图片描述

在这里插入图片描述

2.Set集合实现类

在这里插入图片描述

3. HashSet

3.1 底层原理

在这里插入图片描述

3.1.1 哈希表组成

在这里插入图片描述

3.1.2 哈希值

哈希值:对象的整数表现形式
在这里插入图片描述

在这里插入图片描述

3.1.3 对象的哈希值特点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.2 数据添加元素的过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 HashSet的三个问题

1)
在这里插入图片描述
遍历时 是按照数组的索引从0开始读取数据的。当遇到数组索引中存在链表时,就会把数组当前索引里的链表存储的数据全部读取出来后,再继续遍历数组中的下一个索引。数组索引里的数据存储的是红黑树时,也会按照读取树的方法,把数据全部遍历出来后,再继续遍历下一个数组索引。
在这里插入图片描述
2)
在这里插入图片描述
存储方式不是单一的模式,由 数组,链表,红黑树共同组成。所以无法统一只用一个索引的方式去表述元素。

3)

在这里插入图片描述
用了2个方法去保证元素去重的。
HashCode 方法
equals 方法

3.4 实例:去除重复元素

在这里插入图片描述

package com.zjut.hashset;

import java.util.HashSet;

public class HashSetDemo1 {
    public static void main(String[] args) {
        /*
        * 需求:创建一个储存学生对象的集合,储存多个学生对象
        *       使用程序实现在控制台遍历该集合
        * 要求:学生对象的成员变量值相同,就认为是同一个对象
        * */

        //1.创建学生对象
        Student stu1 = new Student("zhangsan",23);
        Student stu2 = new Student("lisi",24);
        Student stu3 = new Student("wangwu",25);
        Student stu4 = new Student("zhangsan",23);

        //2.创建集合添加学生
        HashSet<Student> hs = new HashSet<>();
        //3.添加元素
        System.out.println(hs.add(stu1));
        System.out.println(hs.add(stu2));
        System.out.println(hs.add(stu3));
        System.out.println(hs.add(stu4));

        System.out.println(hs);
    }
}

package com.zjut.hashset;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

总结
当HashSet存储的是自定义类型时,需要重写 equals,hashCode 方法。不然,默认情况是按照对象的地址计算hash值,而不是按照对象的属性计算。就达不到去除重复元素的效果。

4. LinkedHashSet

在这里插入图片描述

遍历时,从头节点开始遍历,按照双链表的顺序遍历取出。
不是再和HashSet那种遍历方法:从数组的0 索引开始遍历,有重复的元素,然后一根一根链表的去查找。

5. TreeSet

5.1 特点

在这里插入图片描述

5.2 集合默认规则

在这里插入图片描述

字符串从前向后比较
在这里插入图片描述

5.3 例子

package com.zjut.TreeSet;

import java.util.Iterator;
import java.util.TreeSet;


public class TreeSetDemo1 {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<>();

        ts.add(4);
        ts.add(5);
        ts.add(3);
        ts.add(2);
        ts.add(1);

        //打印集合
        System.out.println(ts);
        //遍历集合
        //迭代器
        Iterator<Integer> it = ts.iterator();
        while (it.hasNext()) {
            int i = it.next();
            System.out.println(i);
        }

        System.out.println("------------------------------------");
        //增强for
        for (int t : ts) {
            System.out.println(t);
        }
        System.out.println("------------------------------------");

        //lambda
        ts.forEach( integer -> System.out.println(integer));
    }
}

默认从大到小,排好顺序的
在这里插入图片描述

5.4 两种比较规则

对于自定义的数据类型,可以自定义比较规则。

TreeSet 底层是红黑树,不需要像HashSet一样重写equals,hashCode 方法,才能进行比较。

它有两种比较规则。
在这里插入图片描述

5.4.1 默认排序

在这里插入图片描述

package com.zjut.TreeSet;

import java.util.TreeSet;

public class TreeSetDemo2 {
    public static void main(String[] args) {
        /*
        * 排序方法:
        * 1. Student 实现Comparable接口,重写里面的抽象方法,再指定比较规则
        * */

        //1.创建学生对象
        Student stu1 = new Student("zhangsan",23);
        Student stu3 = new Student("wagnwu",25);
        Student stu2 = new Student("lisi",24);

        //2.创建集合对象
        TreeSet<Student>  ts =new TreeSet<>();
        //3.添加元素
        ts.add(stu1);
        ts.add(stu2);
        ts.add(stu3);
        //4.打印集合
        System.out.println(ts);
    }
}

package com.zjut.TreeSet;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    //this:当前要添加的元素,
    //0:表示已经在红黑树中存在的元素

    //返回值:
    //负数:表示当前要添加的元素是小的,存红黑树的左边
    //正数:表示当前要添加的元素是大的,存红黑树的右边
    //0:表示当前要添加的元素已经存在,舍弃
    public int compareTo(Student o) {
        System.out.println("------------------");
        System.out.println("this:" + this);
        System.out.println("o:" + o);
        //指定排序规则
        //只看年龄:按照年龄的升序排列
        return  this.getAge() - o.getAge()  ;
    }
}

5.4.2 比较器排序

在这里插入图片描述

例子:
TreeSet对象排序练习
在这里插入图片描述

package com.zjut.TreeSet;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo3 {
    public static void main(String[] args) {
        /**
         * 需求:请自行选择比较器排序和自然排序两种方式:
         * 要求:存入四个字符串,“c" ,"ab", "df", "qwer"
         * 按照长度从短到长排序,如果长度一样则按照首字母排序。
         */
        //HashSet集合,字符串默认按照首字母排序,不会按照长度排序

        //1.创建集合 ,传递比较器 Comparator 比较规则
        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            @Override
            //s:要添加的元素
            //t1:表示已经在红黑树中存在的元素
            public int compare(String s, String t1) {
                int i = s.length() - t1.length();
                //如果一样,则按照默认的首字母排序
                i = i == 0 ? s.compareTo(t1) : i;
                return i;
            }
        });

/* 因为Comparator是函数式接口,所以可以使用 lambda 表达式写法
        TreeSet<String> ts = new TreeSet<>(( s,  t1) -> {
                int i = s.length() - t1.length();
                //如果一样,则按照默认的首字母排序
                i = i == 0 ? s.compareTo(t1) : i;
                return i;

        });
*/

        ts.add("c");
        ts.add("ab");
        ts.add("df");
        ts.add("qwer");

        System.out.println(ts);

    }
}

输出:
[ab, c, df, qwer]

5.5. TreeSet对象排序练习

在这里插入图片描述

package com.zjut.TreeSet;

import java.util.TreeSet;

public class TreeSetDemo4 {
    public static void main(String[] args) {

        /*TreeSet排序规则
        * 1.默认排序,自然排序
        * 2.比较器排序
        * 默认情况下,用第一种排序,如果第一种不能满足当前的需求,采用第二种方式
        * */

         //1.创建学生对象
        Student02 st1 = new Student02("zhangsan",23,90,98,89);
        Student02 st2 = new Student02("lisi",24,91,97,88);
        Student02 st3 = new Student02("wangwu",25,90,96,70);
        Student02 st4 = new Student02("zhaoliu",26,60,80,68);
        Student02 st5 = new Student02("qianqi",27,70,77,77);

        //2.创建集合
        //默认选择ArrayList
        //HashSet
        //TreeSet
        TreeSet<Student02> ts = new TreeSet<>() ;
        ts.add(st1);
        ts.add(st2);
        ts.add(st3);
        ts.add(st4);
        ts.add(st5);

        //System.out.println(ts);
        for (Student02 t : ts) {
            System.out.println(t);
        }

    }
}

package com.zjut.TreeSet;

public class Student02 implements Comparable<Student02> {
    private String name;
    private int age;
    private int chinese;
    private int math;
    private int english;

    public Student02() {
    }

    public Student02(String name, int age, int chinese, int math, int english) {
        this.name = name;
        this.age = age;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    @Override
    public String toString() {
        return "Student02{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", chinese=" + chinese +
                ", math=" + math +
                ", english=" + english +
                '}';
    }

    /*
     * 按照总分从高到底 输出到控制台
     * 如果总分一样,按照语文成绩排
     * 如果语文一样,按照数学成绩排
     * 如果数学成绩一样,按照英语成绩排
     * 如果英语成绩一样,按照年龄排
     * 如果年龄一样,按照姓名的首字母排
     * 如果都一样,认为是同一个学生,不存
     * */
    @Override
    public int compareTo(Student02 student02) {
        int sum1 = this.getChinese() + this.getEnglish() + this.getMath();
        int sum2 = student02.getChinese() + student02.getMath() + student02.getEnglish();

        //比较两者总分
        int i = sum1 - sum2;
        //如果总分一样,按照语文成绩排
        i = i == 0 ? this.getChinese() - student02.getChinese() : i;
        //如果语文一样,按照数学成绩排
        i = i == 0 ? this.getMath() - student02.getMath() : i;
        //如果数学成绩一样,按照英语成绩排,(可以省略,因为三门成绩总分一样,而语文,数学成绩一样,那英语成绩肯定一样)
        i = i == 0 ? this.getEnglish() - student02.getEnglish() : i;
        //如果英语成绩一样,按照年龄排
        i = i == 0 ? this.getAge() - student02.getAge() : i;
        //如果年龄一样,按照姓名的首字母排
        i = i == 0 ? this.getName().compareTo(student02.getName()): i;

        return i;
    }
}

在这里插入图片描述

5.6 TreeSet小结

5.6.1 TreeSet集合的特点?

在这里插入图片描述

5.6.2 TreeSet集合自定义排序规则有几种方式?

在这里插入图片描述

5.6.3 方法返回值得特点

在这里插入图片描述

6. 单列集合使用场景

在这里插入图片描述

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

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

相关文章

泛型——List 优于数组

数组与泛型有很大的不同&#xff1a; 1. 数组是协变的&#xff08;covariant&#xff09; 意思是&#xff1a;如果Sub是Super的子类型&#xff0c;则数组类型Sub[] 是数组类型Super[] 的子类型。 2. 泛型是不变的&#xff08;invariant&#xff09; 对于任何两种不同的类型Ty…

Linux下进程间通信

Linux下进程间通信 进程间通信的目的进程间通信的手段的分类管道什么是管道管道原理匿名管道创建匿名管道文件匿名管道的特点匿名管道的4种场景 有名管道有名管道的创建有名管道总结命名管道的打开规则 system V 共享内存共享内存原理建立通信回收共享内存开始通信命令操作共享…

常用的JVM参数选项

目录 打印设置的XX选项及值 堆、栈、方法区等内存大小设置 OutOfMemory相关的选项 垃圾收集器相关选项 GC日志相关选项 其他参数 通过Java代码获取JVM参数 打印设置的XX选项及值 程序运行时JVM默认设置或用户手动设置的XX选项 -XX:PrintCommandLineFlags 打印所有…

Photoshop如何使用绘画和图像修饰之实例演示?

文章目录 0.引言1.给图像添加渐变色效果2.快速创建一副素描画3.清除图像中多余的景物4.快速融合两张图像5.调整图像光影6.人像面部瑕疵修除7.美化眼睛 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及其…

LeetCode 与组合数相关的题目

216. 组合总和 III 方法&#xff1a;递归 class Solution { private:vector<vector<int>> res;vector<int> path;void solve(int k, int goal, int cur, int idx) {if (cur > goal) return;if (path.size() k) {if (cur goal) res.push_back(path);re…

小球下落(dropping balls)uva679

题目描述 原文链接 题目链接 上面中文总结一下&#xff1a; D代表这棵树深度&#xff0c;那么一共就有2^d -1 个结点 每个结点从左到右&#xff0c;从上往下&#xff0c;从1开始递增编号&#xff0c;那么也就是说对于结点k来说&#xff0c;左子结点与右子结点的编号分别为…

C/C++每日一练(20230430)

目录 1. 分割回文串 &#x1f31f;&#x1f31f; 2. 六角填数 ※ 3. 查找书籍 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 分割回文串 给你一个字符串 s&#x…

unity 渲染性能分析工具

目标 既然要优化&#xff0c;肯定要有个目标&#xff1a; pc上一般要求&#xff1a;一秒渲染60帧 移动端&#xff1a;一秒渲染30帧 这应该是最低的要求&#xff0c;如果游戏运行时&#xff0c;游戏帧率有变化&#xff0c;人眼能够明显的感觉到帧率下降。 优化的首要规则是找到…

CMake | 01 - CMake快速上手(3.26.3)

专栏介绍 本专栏记录了博主入门CMake的笔记。 源码仓库欢迎Star&#xff1a;https://github.com/Mculover666/cmake_study。 一、CMake概述 1. 什么是CMake CMake官网&#xff1a;https://cmake.org/ CMake is an open-source, cross-platform family of tools designed t…

17.计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度

说明书 MATLAB代码&#xff1a;计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度 关键词&#xff1a;碳捕集 虚拟电厂 需求响应 优化调度 电转气协同调度 参考文档&#xff1a;《计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度》完全复现 仿真平台&#xff1a…

【Linux从入门到精通】vim的基本使用各种操作详解

文章目录 一、vim编辑器简单介绍 二、vim编辑器的四种模式 2、1 正常/普通/命令模式(Normal mode) 2、2 插入模式(Insert mode) 2、3 末行模式(last line mode) 三、命令模式的相关操作实例 3、1 光标的相关操作 3、2 文本操作 四、插入模式下的相关操作 五、末行模式下的相关操…

FreeRTOS任务的创建(动态方法和静态方法)

文章目录 前言一、FreeRTOS任务基本概念二、动态创建任务三、静态创建任务四、静态创建任务和动态创建任务的区别五、任务的删除总结 前言 本篇文章将介绍FreeRTOS任务的创建&#xff08;动态方法和静态方法&#xff09;&#xff0c;了解什么是任务和任务的具体创建方法。 一…

文件 IO 操作

文章目录 一 文件1.1 文本模式1.2 二进制模式 二 函数2.1fopen()2.2 getc() 和 putc()2.3 fclose()2.4 fprintf() 和 fscanf()2.5 fgets() 和 fputs()2.6 rewind()2.7 fseek() 和 ftell()2.8 fflush()2.9 fgetpos() 和 fsetpos()2.10 feof() 和 ferror()2.11 ungetc()2.12 setv…

[python][vpython]用vpython实现小球砸弹簧代码

代码&#xff1a; from vpython import * # 加载vpython模块s1 canvas(width1200, height500, backgroundcolor.white, centervector(0, 1, 0)) # 定义画布 L0 1.4 # 定义初始高度 natural_length 0.9 # 设置弹簧原长 base_spring box(posvector(0, 0, 0), sizevector…

solidity 安全 如何阻止重入攻击

什么是可重入攻击&#xff1f; 我们使用合约的过程中&#xff0c;经常会遇到这种情况&#xff0c;智能合约能够调用外部的合约&#xff1b;这些外部合约又可以回调到调用他们的智能合约&#xff1b;在这种情况下&#xff0c;我们说智能合约被重新输入&#xff0c;这种情况被称为…

守护进程Daemon

进程组、对话期和控制终端关系 每个会话有且只有一个前台进程组&#xff0c;但会有0个或者多个后台进程组。产生在控制终端上的输入&#xff08;Input&#xff09;和信号&#xff08;Signal&#xff09;将发送给会话的前台进程组中的所有进程。对于输出&#xff08;Output&…

给大家介绍几个手机冷门但好用的小技巧

技巧一&#xff1a;拍照识别植物 手机的拍照识别植物功能是指在使用手机相机时&#xff0c;可以通过对植物进行拍照&#xff0c;并通过植物识别技术&#xff0c;获取植物的相关信息和资料。其主要优点如下&#xff1a; 方便实用&#xff1a;使用拍照识别植物功能&#xff0c;…

Small Tip: 怎么去Schedule一个Analysis for Office的workbook

workbook的query不能是本地的&#xff0c;也就是说不能是在包$Tmp里面的。这种的没办法在BO里面用SSO。也就没办法Schedule。 前提条件有&#xff1a; 1.BO和BW系统的SSO配置得OK。 如果没有SSO&#xff0c;那么每次打开workbook就会有一个要登录BW的弹窗&#xff0c;这样是…

从零开始学习Linux运维,成为IT领域翘楚(三)

文章目录 &#x1f525;Linux超级用户与伪用户&#x1f525;Linux文件基本属性&#x1f525;Linux权限字与权限操作 &#x1f525;Linux超级用户与伪用户 Linux下用户分为三类&#xff1a;超级用户、普通用户、伪用户 ⭐ 超级用户&#xff1a;用户名为root&#xff0c;具有一切…

初识 OPC

为什么需要OPC&#xff1f; 随着自动化的发展&#xff0c;工厂的自动化程度越来越高&#xff0c;面临着问题&#xff1a; 设备之间&#xff0c;设备与应用程序之间交互数据 不同产商设备/应用程序具有不同接口/通信协议&#xff0c;如何简单快速连接&#xff1f;采集的数据及…