(二十六)Set系列集合

news2025/1/13 19:47:03

简介:

  • Set集合,基础自Collection。特征是插入无序,不可指定位置访问。
  • Set集合的实现类可说是基于Map集合去写的。通过内部封装Map集合来实现的比如HashSet内部封装了HashMap。
  • Set集合的数据库不能重复(== 或 eqauls)的元素
  • Set集合的常用实现类有 HashSet TreeSet

1.Set集合实现类特点

        HashSet:无序,不重复,无索引;

        LinkedHashSet:有序,不重复,无索引;

①HashSet底层原理

        HashSet集合底层采取哈希表存储的数据。

        哈希表是一种对于增删改查数据性能都较好的结构。

1.哈希表

        哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数值。

Object类的API:

        public int hashcode() 返回对象的哈希值

2.对象的哈希值特点

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

        默认情况下,不同对象的哈希值是不同的。

3.代码演示:

import java.util.*;
​
/**哈希值  同一对象的哈希值是相同的  不同对象的哈希值是不同的
 * API:
 *public int hashcode()  返回对象的哈希值
 */
public class Set_Demo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();//经典代码  无序,不重复,无索引
        Set<String> set1 = new LinkedHashSet<>();//有序 不重复 无索引
        Set<String> set2 = new TreeSet<>();//排序 不重复 无索引
        set.add("JAVA");
        set.add("JAVA");
        set.add("MySQL");
        set.add("MYSQL");
        set.add("HTML");
        set.add("HTML");
        System.out.println(set);
        //哈希值
        String name = "hertkvs";
        System.out.println(name.hashCode());
        String name1 = "hvammuras";
        System.out.println(name1.hashCode());
    }
}

6.Set集合的底层原理是什么样的?

        JDK8以前,哈希表:底层使用数组+链表组成;

        JDK8以后,哈希表:底层采用数组+链表+红黑树组成。

4.案例:Set集合去重复

        需求:

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

        分析:

                ①定义学生类,创建HashSet集合对象,创建学生对象;

                ②把学生添加到集合;

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

                ④遍历集合(增强for)

学生类:

import java.util.Objects;
​
public class Student {
    private String name;
    private int age;
    private char sex;
​
    public Student(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
​
    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 char getSex() {
        return sex;
    }
​
    public void setSex(char sex) {
        this.sex = sex;
    }
​
    @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 && sex == student.sex && Objects.equals(name, student.name);
    }
​
    @Override
    public int hashCode() {
        return Objects.hash(name, age, sex);
    }
​
    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

main类:

import java.util.HashSet;
import java.util.Set;
​
public class HashSet_Test {
    public static void main(String[] args) {
        Set<Student> sets = new HashSet<>();
​
        Student s1 = new Student("无恙",10,'男');
        Student s2 = new Student("山河",24,'男');
        sets.add(s1);
        sets.add(s2);
​
        System.out.println(sets);
    }
}

②LinkedHashSet

1.LinkedHashSet集合概述和特点

        有序,不重复,无索引;

        这里的有序指的是保证存储和取出的元素顺序一致;

2.原理:

        底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。

③TreeSet

1.概述和特点

        不重复,无索引,可排序

        可排序:按照元素的大小默认升序(由小到大)排序。

        TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。

        注意:

                TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。

2.TreeSet集合默认的规则

        对于数值类型:Integer,Double,官方默认按照大小进行升序排序。

        对于字符串类型:默认按照首字符的编号升序排序。

        对于自定义类型如Student对象,TreeSet无法直接排序。

④总结

1.如果希望元素可以重复,又有索引,索引查询要快?

        用ArrayList集合,基于数组的。(用的最多)

2.如果希望元素可以重复,又有索引,增删首尾操作要快?

        用LinkedList集合,基于链表的。

3.如果希望增删改查都快,但元素不重复,无序,无索引?

        用HashSet集合,基于哈希表的。

4.如果希望增删改查都快,但元素不重复,有序,无索引?

        用LinkedHashSet集合,基于哈希表和双链表的。

5.如果要对对象进行排序。

        用TreeSet集合,基于红黑树,后续也可以用List集合实现排序。

⑤可变参数

1.概述:

        可变参数用在形参中可以接收多个数据;

        可变参数的格式: 数据类型....参数名称

2.可变参数的作用:

        传输参数非常灵活,方便。可以不传输参数,可以传输1个或者多个,也可以传输一个数组;

        可变参数在方法内部本质上就是一个数组;

3.代码演示:

import java.util.Arrays;
​
/*
可变参数
 */
public class Charge_Demo7 {
    public static void main(String[] args) {
        sum();//不传参数
        sum(10);//传输一个参数
        sum(11,22,33);//传输多个参数
        sum(new int[]{11,22,33,44});//传输一个数组
    }
​
    private static void sum(int...nums) {
        //注意:可变参数在方法内部其实就是一个数组
        System.out.println("元素个数:"+nums.length);
        System.out.println("元素内容"+ Arrays.toString(nums));
    }
}

4.可变参数的注意事项:

        1.一个形参列表中可变参数只能有一个;

        2.可变参数必须放在形参列表的最后面;

⑥集合工具类Collections

1.概述:

        ①java.utils.Collections是集合工具类

        ②作用:Collections并不属于集合,是用来操作集合的工具类。

2.Collections常用API

 

3.代码演示:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
​
/**Collections  API  不属于集合,用来操作集合的集合工具类
 * public ststic boolean addAll(Collection<? super T> c,T... element)  批量添加元素
 *public static void shuffle(list<?> list)  打乱集合顺序
 * public static <T> void sort (list<T> list)  集合按照默认规则排序
 * public static <T> void sort (list<T> list,comparator<? super T> c)  将集合中元素按指定规则排序
 */
public class Collections_Demo2 {
    public static void main(String[] args) {
        //1、批量添加元素
        List<String> names = new ArrayList<>();
        Collections.addAll(names,"楚风","皇莆嵩","太史慈");
        System.out.println(names);
        //2、打乱集合顺序、只能打乱list集合顺序
        Collections.shuffle(names);
        System.out.println(names);
        //3、默认集合排序
        List<Integer> sets =new ArrayList<>();//SHIFT+F6  快捷键:同步修改多个相同变量
        Collections.addAll(sets,12,53,43,24);
        System.out.println(sets);
        Collections.sort(sets);
        System.out.println(sets);
​
    }
}

4.Collections排序相关API

使用范围:只能对于List集合的排序

排序方式一:

 

注意:

本方法不可以直接对自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable接口。

排序方式二:

 

5.案例:斗地主游戏

        需求:

                在启动游戏房间的时候,提前准备好54张牌,完成洗牌,发牌,牌排序,逻辑。

        分析:

                ①当系统启动的同时需要准备好数据的时候,就可以用静态代码块了。

                ②洗牌就是打乱牌的顺序。

                ③定义三个玩家,依次发出51张牌。

                ④给玩家的牌进行排序。

                ⑤输出每个玩家的牌数据。

牌类:

public class Card {
    private  String size;
    private String color;
    private int index;//牌的大小
    public Card() {
    }
​
    public Card(String size, String color,int index) {
        this.size = size;
        this.color = color;
        this.index = index;
    }
​
    public int getIndex() {
        return index;
    }
​
    public void setIndex(int index) {
        this.index = index;
    }
​
    public String getSize() {
        return size;
    }
​
    public void setSize(String size) {
        this.size = size;
    }
​
    public String getColor() {
        return color;
    }
​
    public void setColor(String color) {
        this.color = color;
    }
​
    @Override
    public String toString() {
        return size+color;
    }
}

实现类:

import java.util.*;
import java.util.List;
​
public class Poker {
    //定义静态集合存储牌
    public static List<Card> allcards = new ArrayList<Card>();
    //定义静态代码块初始化牌数据
    static {
        //点数确定  个数确定  类型确定  使用数组
        String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        //定义花色  个数确定  类型确定  使用数组
        String[] colors = {"♣","♠","♥","♦"};
        //组合点数和花色
        int index = 0;
        for (String size : sizes) {
            index++;
            for (String color : colors) {
                //封装成一个牌对象
                Card c = new Card(size,color,index);
                //存入集合
                allcards.add(c);
            }
        }
        //再添加大小王
        Card c1 = new Card("","🃏",++index);
        Card c2 = new Card("","🤡",++index);
        Collections.addAll(allcards,c1,c2);
        System.out.println("新牌: "+allcards);
    }
    public static void main(String[] args) {
        // STOPSHIP: 2022/5/20
        Collections.shuffle(allcards);
        System.out.println("洗牌后:" + allcards);
​
        //发牌(定义三个集合容器放置三个玩家)
        List<Card> w1 = new ArrayList<>();
        List<Card> w2 = new ArrayList<>();
        List<Card> w3 = new ArrayList<>();
​
        //开始发牌(剩余三张)
        for (int i = 0; i < allcards.size()-3; i++) {
            //先拿到当前牌对象
            Card c = allcards.get(i);
            if (i%3 == 0) {
                //接牌
                w1.add(c);
            } else if (i%3==1) {
                w2.add(c);
            } else if (i%3==2) {
                w3.add(c);
            }
        }
        //拿最后三张牌
        List<Card> lastTreeCards = allcards.subList(allcards.size()-3,allcards.size());
        //给玩家的牌排序(从大到小)
        sortCast(w1);
        sortCast(w2);
        sortCast(w3);
        //输出玩家的牌
        System.out.println("玩家一:"+w1);
        System.out.println("玩家二:"+w2);
        System.out.println("玩家三:"+w3);
        System.out.println("最后三张底牌:"+lastTreeCards);
    }
​
    private static void sortCast(List<Card> cards) {
        Collections.sort(cards, new Comparator<Card>() {
            @Override
            public int compare(Card o1, Card o2) {
                //知道牌的大小,指定规则
                return o1.getIndex()-o2.getIndex();
            }
        });
    }
}

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

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

相关文章

AxMath使用教程(持续更新中)

前言 这两天学了学Latex&#xff0c;主要是为了以后写毕业论文做铺垫&#xff0c;而且Latex在数学公式这一方面&#xff0c;要比Word方便许多&#xff0c;于是我就下载了一款国产的公式编辑器——AxMath。永久会员不贵&#xff0c;只要36元&#xff0c;而且软件很好用&#xf…

【自然语言处理】情感分析(一):基于 NLTK 的 Naive Bayes 实现

情感分析&#xff08;一&#xff09;&#xff1a;基于 NLTK 的 Naive Bayes 实现朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类器可以用来确定输入文本属于某一组类别的概率。例如&#xff0c;预测评论是正面的还是负面的。 它是 “朴素的”&#xff0c;它假设文本中的单…

机器学习: Label vs. One Hot Encoder

如果您是机器学习的新手&#xff0c;您可能会对这两者感到困惑——Label 编码器和 One-Hot 编码器。这两个编码器是 Python 中 SciKit Learn 库的一部分&#xff0c;它们用于将分类数据或文本数据转换为数字&#xff0c;我们的预测模型可以更好地理解这些数字。今天&#xff0c…

图机器学习-节点嵌入(Node Embedding)

图机器学习-节点嵌入(Node Embedding) Node Embedding简单点来说就是将一个node表示为一个RdR^dRd的向量。 EncoderDecoder Framework 我们首先需要设计一个encoder对节点进行编码。既然要比较相似度那么我就需要定义节点的相似度。同时我们还需要定义一个decoder&#xff0…

Java线程的生命周期的五种状态

在java中&#xff0c;任何对象都要有生命周期&#xff0c;线程也不例外&#xff0c;它也有自己的生命周期。当Thread对象创建完成时&#xff0c;线程的生命周期便开始了&#xff0c;当run()方法中代码正常执行完毕或者线程抛出一个未捕获的异常(Exception)或者错误(Error)时&am…

通信原理简明教程 | 数字基带传输

文章目录1数字基带传输系统的基本组成2 数字基带信号及其频域特性2.1 基本码型2.2 常用码型2.3 数字基带信号的功率谱3 码间干扰3.1 码间干扰的概念&#xff08;ISI&#xff09;3.2 无码间干扰传输的条件3.3 无码间干扰的典型传输波形4 部分响应和均衡技术&#xff08;*&#x…

java+ssm网上书店图书销售评价系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 2 第3章 系统分析 4 3.1 需求分析 4 3.2 系统可行性分析 4 3.2.1技术可行性&#xff1a;技术背景 4 3.2.2经…

【蓝桥云课】位运算

一、原码、反码、补码 原码&#xff1a;符号位&#xff08;正数为0、负数为1&#xff09;二进制数 反码&#xff1a;正数的反码正数的原码&#xff1b;负数的反码负数的原码除符号位外按位求反 补码&#xff1a;正数的补码正数的反码&#xff1b;负数的补码负数的反码1 整数原…

基于SPN实现的密码学课程设计(附完整代码)

就是如图所示的一个过程! 1.1 初次写SPN 初代SPN 为了方便的使用S盒P盒的那些运算(直接使用数组, 而不使用位运算),所以想起了C语言课上学的

HTML基本常用标签

<!doctype html> <html> <head> <title>HTML的常用标签</title> <meta charset"UTF-8"> <!-- 这行代码是告诉浏览器使用UTF-8字符集打开; 而不是设置当前页面的编码方式 --> </head> <bo…

SSH命令

概念 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中建立安全隧道&#xff08;secure channel&#xff09;来实现SSH客户端与服务器之间…

结构体的内存对齐与位段的实现

本篇文章重点介绍结构体相关知识以及深入介绍的结构体的内存对齐与位段的实现 ———————————— 内存对齐位段——————————————————一.结构体1.结构体类型的声明1.1基础知识1.2声明1.3特殊声明1.4结构体的自引用1.5结构体变量的定义和初始化与访问2.结…

C 语言零基础入门教程(八)

C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false…

JVM快速入门学习笔记(四)

15.GC &#xff1a;垃圾回收机制 垃圾回收的区域只有在堆里面&#xff08;方法区在堆里面&#xff09; 15.1 垃圾回收 GC JVM 在进行垃圾回收&#xff08;GC&#xff09;时&#xff0c;并不是堆这三个区域统一回收。大部分时候&#xff0c;回收都是新生代~   1.新生代   …

Opencv项目实战:19 手势控制鼠标

目录 0、项目介绍 1、效果展示 2、项目搭建 3、项目代码展示 HandTrackingModule.py VirtualMouse.py 4、项目资源 5、项目总结 0、项目介绍 在Opencv项目实战&#xff1a;15 手势缩放图片中&#xff0c;我们搭建了HandTrackingModule模块&#xff0c;但在这里你还得用…

离散数学与组合数学-04图论上

文章目录离散数学与组合数学-04图论上4.1 图的引入4.1.1 图的示例4.1.2 无序对和无序积4.1.3 图的定义4.2 图的表示4.2.1 集合表示和图形表示4.2.2 矩阵表示法4.2.3 邻接点与邻接边4.3 图的分类4.3.1 按边的方向分类4.3.2 按平行边分类4.3.3 按权值分类4.3.4 综合分类方法4.4 图…

MySQL —— 表操作

目录 一、创建表 二、创建表的案例 三、查看表的结构 四、修改表 五、删除表 一、创建表 语法&#xff1a; CREATE TABLE [IF NOT EXISTS] table_name(field1 datatype1 [COMMENT 注释信息],field2 datatype2 [COMMENT 注释信息],field3 datatype3 [COMMENT 注释信息] )…

通信原理简明教程 | 模拟信号的数字化传输

文章目录1 抽样及抽样定理1.1 抽样1.2 抽样定理2 量化及量化信噪比2.1 均匀量化2.2 量化误差和量化信噪比2.3 非均匀量化3 编 码3.1常用的二进制码组3.2 均匀量化编码方法3.3 A律13折线编码4 脉冲编码调制系统4.1 PCM系统的码元速率4.2 PCM系统的抗噪声性能5 预测编码5.1 差分脉…

【Kotlin】扩展函数 ③ ( 定义扩展文件 | 重命名扩展函数 | Kotlin 标准库扩展函数 )

文章目录一、定义扩展文件二、重命名扩展函数三、Kotlin 标准库扩展函数一、定义扩展文件 如果定义的 扩展函数 需要在 多个 Kotlin 代码文件 中使用 , 则需要在 单独的 Kotlin 文件 中定义 , 该文件被称为 扩展文件 ; 定义 标准库函数 的 Standard.kt 就是 独立的 扩展文件 ;…

IDEA搭建Finchley.SR2版本的SpringCloud父子基础项目-------Feign负载均衡

1.概述 官网&#xff1a;http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口&#xff0c;然后在上面添加注解&#xff0c;同时也支…