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

news2024/12/23 2:01:07

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/477672.html

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

相关文章

JavaScript 知识总结上篇(更新版)

1. 为什么 JS 是单线程的&#xff1f; 因为JS里面有可视的Dom&#xff0c;如果是多线程&#xff0c;这个线程正在删除DOM节点&#xff0c;另一个线程正在编辑Dom节点&#xff0c;导致浏览器不知道该听谁的 2.如何理解同步和异步&#xff1f; 同步&#xff1a;按照代码书写顺…

Linux——中断和时间管理(下)

目录 延时控制 定时操作 低分辨率定时器 高分辨率定时器 练习 延时控制 在硬件的操作中经常会用到延时&#xff0c;比如要保持芯片的复位时间持续多久、芯片复位后要至少延时多长时间才能去访问芯片、芯片的上电时序控制等。为此&#xff0c;内核提供了一组延时操作函数。…

DDD系列:三、Repository模式

为什么需要Repository&#xff1f; ​ Anemic Domain Model&#xff08;贫血领域模型&#xff09;特征&#xff1a; 有大量的XxxDO对象&#xff1a;这里DO虽然有时候代表了Domain Object&#xff0c;但实际上仅仅是数据库表结构的映射&#xff0c;里面没有包含&#xff08;或…

kafka整理

kafka整理 一、kafka概述 kafka是apache旗下一款开源的顶级的消息队列的系统, 最早是来源于领英, 后期将其贡献给apache, 采用语言是scala.基于zookeeper, 启动kafka集群需要先启动zookeeper集群, 同时在zookeeper记录kafka相关的元数据 kafka本质上就是消息队列的中间件产品…

Codeforces Round 867 (Div. 3)(A-G2)

文章目录 A. TubeTube Feed1、题目2、分析3、代码&#xff0c; B. Karina and Array1、题目2、分析3、代码 C. Bun Lover1、问题2、分析&#xff08;1&#xff09;观察样例法&#xff08;2&#xff09;正解推导 3、代码 D. Super-Permutation1、问题2、分析&#xff08;1&#…

力扣第343场周赛

第一次力扣&#xff0c;等大二寒暑假&#xff0c;有时间再来系统刷题 目录 &#x1f33c;前言 &#x1f33c;一&#xff0c;6341.保龄球游戏的获胜者 &#x1f33c;二&#xff0c;6342.找出叠涂元素 &#x1f333;第一次 -- 超时 &#x1f333;第二次 -- AC &#x1f33c…

二叉树相关的简单递归oj

二叉树相关的简单递归oj 前言题目二叉树的前序遍历相同的树判断单值二叉树对称二叉树另一棵树的子树创建二叉树并遍历 前言 这篇博客主要是博主感觉对二叉树oj题目不太熟悉&#xff0c;随便整理的一下题目和解答&#xff0c;方便复习&#xff0c;所以讲题部分主要以我自己以及为…

Java 基础入门篇(二)——— Java 基础语法

文章目录 一、注释二、字面量三、变量3.1 变量概述3.2 变量在计算机中的底层原理 四、数据类型五、关键字、标志符六、类型转换6.1 自动类型转换6.2 表达式的自动类型转换6.3 强制类型转换 七、运算符7.1 基本算数运算符7.2 符号做连接符7.3 自增自减运算符7.4 赋值运算符7.5 …

【C++技能树】类的六个成员函数Ⅰ --构造、析构、拷贝构造函数

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法…感兴趣就关注我吧&#xff01;你定不会失望。 本篇导航 0.this指针1.Class默认成员函数2.构造函数调用规则: 3.析构函数4.拷贝构造函数 0.this指针 在开始本章内容之前&#xff0c;先浅…

Channel-wise Knowledge Distillation for Dense Prediction(ICCV 2021)原理与代码解析

paper&#xff1a;Channel-wise Knowledge Distillation for Dense Prediction official implementation&#xff1a;https://github.com/irfanICMLL/TorchDistiller/tree/main/SemSeg-distill 摘要 之前大多数用于密集预测dense prediction任务的蒸馏方法在空间域spatial…

(求正数数组的最小不可组成和,养兔子)笔试强训

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 目录 文章目录 一、选择题1 二、[编程题]养兔子 三、[编程题]求正数数组的最小不可组成和 一、选择题1 reflection是如何工作的__牛客网 (nowcoder.com) 考虑下面这个简单的例子&…

大数据Doris(八):Broker部署和集群启停脚本

文章目录 Broker部署和集群启停脚本 一、Broker部署 1、准备Broker 安装包 2、启动 Broker

PyQt6剑指未来-日期和时间

前言 时间和日期是软件开发中非常重要的概念。在PyQt6中&#xff0c;时间和日期模块提供了处理日期、时间和日期时间的类和函数&#xff0c;以及管理时区和夏令时的特性。这些模块提供了可靠和易于使用的工具&#xff0c;使得在PyQt6中处理和呈现时间和日期的操作变得轻松起来…

Java中Lambda表达式(初学到精通)

目录 一、Lambda表达式是什么&#xff1f;什么场景下使用Lambda&#xff1f; 1.Lambda 表达式是什么 2.函数式接口是什么 第二章、怎么用Lambda 1.必须有一个函数式接口 2.省略规则 3.Lambda经常用来和匿名内部类比较 第三章、具体使用举例&#xff08;&#xff09; 1.案…

跳跃游戏类题目 总结篇

一.跳跃游戏类题目简单介绍 跳跃游戏是一种典型的算法题目&#xff0c;经常是给定一数组arr&#xff0c;从数组的某一位置i出发&#xff0c;根据一定的跳跃规则&#xff0c;比如从i位置能跳arr[i]步&#xff0c;或者小于arr[i]步&#xff0c;或者固定步数&#xff0c;直到到达某…

C++ 链表概述

背景 当需要存储大量数据并需要对其进行操作时&#xff0c;常常需要使用到链表这种数据结构。它可以用来存储一系列的元素并支持插入、删除、遍历等操作。 概念 一般来说&#xff0c;链表是由若干个节点组成的&#xff0c;每个节点包含了两个部分的内容&#xff1a;存储的数…

【嵌入式环境下linux内核及驱动学习笔记-(6-内核 I/O)-阻塞与非阻塞】

目录 1、阻塞与非阻塞1.1 以对recvfrom函数的调用及执行过程来说明阻塞的操作。1.2 以对recvfrom函数的不断轮询调用为例&#xff0c;说明非阻塞时进程的行为。1.3 简单介绍内核链表及等待队列1.4 等待队列1.4.1 定义等待队列头部&#xff08;wait_queue_head_t&#xff09;1.4…

vue动态添加多组数据添加正则限制

如图新增多条数据&#xff0c;如果删除其中一条正则校验失败的数据&#xff0c;提示不会随之删除&#xff0c;若想提示删除并不清空数据 delete (item, index) {this.applicationForm.reserveInfo.forEach((v, i) > {if (i index) {this.$refs.formValidate.fields.forEac…

UFT——操作模块

示例一 创建一个可重复利用的登录测试更改Action的名称。使用本地数据表。创建一个主调用测试。建立测试迭代。处理缺失的Action。 分析&#xff1a;就是创建一个只有登录的测试起名为login&#xff0c;然后在创建一个主测试起名字比如main&#xff0c;在main中&#xff0c;调用…