当前位置: 首页 > news >正文

Java Set集合

7 Set集合

7.1 Set集合的概述和特点

  • Set集合的特点
    • 不包含重复元素的集合
    • 没有带索引的方法,所以不能使用普通for循环
  • Set集合是接口通过实现类实例化(多态的形式)
    • HashSet:添加的元素是无序,不重复,无索引的
    • LinkedHashSet: 添加的元素是有序,不重复,无索引的
    • TreeSet: 不重复,无索引,按照大小默认升序排列
package ceshi;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class SetDemo {public static void main(String[] args) {//创建Set集合对象Set<String> set = new HashSet<>();//添加元素set.add("java");set.add("python");set.add("scala");//不包含重复元素set.add("java");//两种遍历方式for(String s:set) {System.out.println(s);/*pythonjavascala*/}System.out.println("--------");Iterator<String> it = set.iterator();while(it.hasNext()) {String s = it.next();System.out.println(s);/*pythonjavascala*/}}
}

7.2 哈希值

  • 哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
  • Object类中有一个方法可以获取对象的哈希值
    public int hashCode():返回对象的哈希码值
  • 对象的哈希值特点
    • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
    • 默认情况下,不同对象的哈希值是不同的。而重写hashCode0方法,可以实现让不同对象的哈希值相同
package ceshi;public class HashDemo {public static void main(String[] args) {//创建学生对象Student s1 = new Student("y1",10);//同一个对象多次调用hashCode()方法哈希值相同System.out.println(s1.hashCode()); //460141958System.out.println(s1.hashCode()); //460141958System.out.println("---------");//默认情况下,不同对象哈希值不同;重写hashCode()方法就可以使哈希值相同Student s2 = new Student("y2",20);System.out.println(s2.hashCode()); //1163157884System.out.println("---------");System.out.println("java".hashCode()); //3254818System.out.println("python".hashCode()); //-973197092System.out.println("scala".hashCode()); //109250886System.out.println("---------");System.out.println("无".hashCode()); //26080System.out.println("敌".hashCode()); //25932}
}

7.3 数据结构之哈希表

  • JDK8之前,底层采用数组+链表实现,可以说是一个元索为链表的数组(哈希表 = 数组 + 链表 + (哈希算法))
  • JDK8以后,在长度比较长的时候,底层实现了优化(哈希表 = 数组 + 链表 + 红黑树 + (哈希算法))
  • 当链表长度超过 8 时,将链表转换为红黑树,这样大大减少了查找时间
    在这里插入图片描述

7.4 HashSet集合概述和特点

  • HashSet集合特点
    • 底层数据结构是哈希表
    • 对集合的迭代顺序不作任何保证 ,也就是说不保证存储和取出的元素顺序一致
    • 没有带索引的方法,所以不能使用普通for循环遍历
    • 由于是Set集合, 所以是不包含重复元素的集合
package ceshi;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args) {HashSet<String> hs = new HashSet<>();hs.add("java");hs.add("python");hs.add("scala");hs.add("scala");for(String s:hs) {System.out.println(s);/*pythonjavascala*/}}
}

7.5 HashSet集合保证元素唯一性源码分析(重点面试常考)

在这里插入图片描述

HashSet<String> hs = new HashSet<>();hs.add("java");hs.add("python");hs.add("scala");hs.add("scala");for(String s:hs) {System.out.println(s);/*pythonjavascala*/}
-----------------------------------
public boolean add(E e) {return map.put(e, PRESENT)==null;
}static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
public V put(K key, V value) {return putVal(hash(key), key, value, false, true); //上个方法的返回的值是hash(key)的值
}
//hash值和元素的hashCode()方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;//如果哈希表未初始化就对其初始化if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//根据对象的哈希值计算对象的存储位置,if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null); //如果该位置没有元素,就存储新元素//有元素就走elseelse {Node<K,V> e; K k;//存入的元素和以前的元素比哈希值if (p.hash == hash && //二、如果哈希值相同,调用对象的equals()比较内容是否相同//1、如果内容不同equals()返回false,就走一把元素添加到集合//2、如果内容相同返回true,说明元素重复,走e = p;不存储((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);//一、如果哈希值不同,就走else存储元素到集合else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null); //新元素添加到集合if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}
  • HashSet集合存储元素:要保证元素唯一性需要重写hashCode()equals()方法

  • 案例
    在这里插入图片描述

  • Student类

package ceshi;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;}//重写快捷键:Fn+Alt+insert,选择equals() and hashCode()@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
}
  • 测试类
package ceshi;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args) {HashSet<Student> hs = new HashSet<>();Student s1 = new Student("y1",10);Student s2 = new Student("y2",20);Student s3 = new Student("y3",30);Student s4 = new Student("y3",30);hs.add(s1);hs.add(s2);hs.add(s3);hs.add(s4);for(Student s: hs) {System.out.println(s.getName()+","+s.getAge());/*y3,30y2,20y1,10y3,30;s4内容和s3重复并存入了,需要重写hashCode()和equals()*///重写后/*y1,10y3,30y2,20*/}}
}

7.6 LinkedHashSet集合概述和特点

  • LinkedHashSet集合特点
    • 哈希表和链表实现的Set接口, 具有可预测的迭代次序
    • 由链表保证元素有序, 也就是说元索的存储和取出顺序是一致的
    • 由哈希表保证元索唯一, 也就是说没有重复的元素
package ceshi;import java.util.LinkedHashSet;public class LinkedHashSetDemo {public static void main(String[] args) {LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();linkedHashSet.add("java");linkedHashSet.add("python");linkedHashSet.add("scala");linkedHashSet.add("scala");for(String s:linkedHashSet) {System.out.println(s);/*javapythonscala*/}}
}

7.7 TreeSet集合概述和特点

  • TreeSet集合特点

    • 元素有序, 这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
      TreeSet():根据其元素的自然排序进行排序
      TreeSet(Comparator comparator):根据指定的比较器进行排序
    • 没有带索引的方法,所以不能使用普通for循环遍历
    • 由于是Set集合,所以不包含重复元素的集合
package ceshi;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {TreeSet<Integer> ts = new TreeSet<>();//jdk5以后添加元素自动装箱int》integerts.add(10);ts.add(40);ts.add(30);ts.add(50);ts.add(20);ts.add(30);for(Integer i:ts) {System.out.println(i);/*1020304050*/}}
}

7.8 自然排序Comarable的使用

  • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法

  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

  • 结论:

    • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
    • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
  • Student类

package ceshi;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;}@Overridepublic int compareTo(Student s) {
//        return 0; //返回0说明元素是重复的,只能存一个元素
//        return 1; //整数是升序排序
//        return -1; //负数是倒叙排序//按照年龄排序int num = this.age-s.age; //this是s2,s是s1//年龄相同时,按照名字字母排序int num2 = num==0 ? this.name.compareTo(s.name):num;return num2;}
}
  • 测试
package ceshi;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<>();Student s1 = new Student("y1",10);Student s2 = new Student("y3",30);Student s3 = new Student("y2",20);Student s4 = new Student("y4",40);Student s5 = new Student("a4",40); //判断按字母排序Student s6 = new Student("y4",40); //判断会存储重复值吗ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);for(Student s:ts) {System.out.println(s.getName()+","+s.getAge());/*y1,10y2,20y3,30a4,40y4,40*/}}
}

7.9 比较器排序Comparator[kəmˈpɜrətər]的使用

  • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
  • 结论
    • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元索进行排序的
    • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,T o2)方法
    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
package ceshi;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;}}
  • 测试
package ceshi;import java.util.Comparator;
import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {int num = s1.getAge() - s2.getAge();int num2 = num==0? s1.getName().compareTo(s2.getName()):num;return num2;}});Student s1 = new Student("y2",20);Student s2 = new Student("y1",10);Student s3 = new Student("y3",30);Student s4 = new Student("y4",40);ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);for(Student s:ts) {System.out.println(s.getName()+","+s.getAge());}}
}

7.10 案例:不重复随机数

在这里插入图片描述

package ceshi;import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;public class SetDemo {public static void main(String[] args) {
//        Set<Integer> set = new HashSet<>();Set<Integer> set = new TreeSet<>();Random r = new Random();//判断集合是否《10while(set.size()<10) {int number = r.nextInt(20)+1;set.add(number); //把随机数添加到集合}for (Integer i:set) {System.out.print(i+" "); //1(哈希set集合):16 17 2 20 8 9 10 11 14 15//2(TreeSet集合):1 3 4 5 6 7 8 10 16 19 }}
}

相关文章:

Java Set集合

7 Set集合 7.1 Set集合的概述和特点 Set集合的特点 不包含重复元素的集合没有带索引的方法&#xff0c;所以不能使用普通for循环 Set集合是接口通过实现类实例化&#xff08;多态的形式&#xff09; HashSet&#xff1a;添加的元素是无序&#xff0c;不重复&#xff0c;无索引…...

【手写 Vuex 源码】第七篇 - Vuex 的模块安装

一&#xff0c;前言 上一篇&#xff0c;主要介绍了 Vuex 模块收集的实现&#xff0c;主要涉及以下几个点&#xff1a; Vuex 模块的概念&#xff1b;Vuex 模块和命名空间的使用&#xff1b;Vuex 模块收集的实现-构建“模块树”&#xff1b; 本篇&#xff0c;继续介绍 Vuex 模…...

EOC第六章《块与中枢派发》

文章目录第37条&#xff1a;理解block这一概念第38条&#xff1a;为常用的块类型创建typedef第39条&#xff1a;用handler块降低代码分散程度第41条&#xff1a;多用派发队列&#xff0c;少用同步锁方案一&#xff1a;使用串行同步队列来将读写操作都安排到同一个队列里&#x…...

八、Git远程仓库操作——跨团队成员的协作

前言 前面一篇博文介绍了git团队成员之间的协作&#xff0c;现在在介绍下如果是跨团队成员的话&#xff0c;如何协作&#xff1f; 跨团队成员协作&#xff0c;其实就是你不属于那个项目的成员&#xff0c;你没有权限向那个仓库提交代码。但是github还有另一种 pull request&a…...

算法刷题打卡第88天:字母板上的路径

字母板上的路径 难度&#xff1a;中等 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "…...

UVa The Morning after Halloween 万圣节后的早晨 双向BFS

题目链接&#xff1a;The Morning after Halloween 题目描述&#xff1a; 给定一个二维矩阵&#xff0c;图中有障碍物和字母&#xff0c;你需要把小写字母移动到对应的大写字母位置&#xff0c;不同的小写字母可以同时移动&#xff08;上下左右四个方向或者保持不动 &#xff0…...

Connext DDS属性配置参考大全(3)

Transport传输dds.participant.logging.time_based_logging.process_received_messagedds.participant.logging.time_based_logging.process_received_message.timeout...

Docker-安装Jenkins-使用jenkins发版Java项目

文章目录0.前言环境背景1.操作流程1.1前期准备工作1.1.1环境变量的配置1.2使用流水线的方式进行发版1.2.1新建流水线任务1.2.2流水线操作工具tools步骤stages步骤1:拉取代码编译步骤2:发送文件并启动0.前言 学海无涯&#xff0c;旅“途”漫漫&#xff0c;“途”中小记&#xff…...

spring 中的 Bean 是否线程安全

文章目录结论1、spring中的Bean从哪里来&#xff1f;2、spring中什么样的Bean存在线程安全问题&#xff1f;3、如何处理spring Bean的线程安全问题&#xff1f;结论 其实&#xff0c;Spring 中的 Bean 是否线程安全&#xff0c;其实跟 Spring 容器本身无关。Spring框架中没有提…...

微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…...

C++入门教程||C++ 数据类型||C++ 变量类型

C 数据类型 使用编程语言进行编程时&#xff0c;需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着&#xff0c;当您创建一个变量时&#xff0c;就会在内存中保留一些空间。 您可能需要存储各种数据类型&#xff08;比如字符型、宽字符型、整型…...

【visio使用技巧】图片导出pdf时去掉多余空白

问题 在visio导出pdf格式的图片时&#xff0c;往往会存在多余的白边&#xff0c;如下图所示&#xff1a; 解决方法 依次点击&#xff1a;菜单栏→文件→选项→自定义功能区→勾选“开发工具”→确定。 依次点击菜单栏→开发工具→显示ShapeSheet→页→Print Properties→将…...

Rust语言之Option枚举类型

概述 Option是Rust语言设计中最重要的枚举类型之一&#xff0c;它编码了其它语言中空值与非空值的概念&#xff0c;差异在于&#xff0c;Rust不会允许你像其它语言一样以非空值的方式来使用一个空值&#xff0c;这避免了很多错误。Option在标准库中的定义如下&#xff1a; pu…...

基于TimeQuest时序优化原理和方法

&#x1f4a1; 回顾基于RTL逻辑时序优化的基本思路&#xff0c;在关键路径中插入寄存器来优化时序 分析最坏路径 通过前面对TimeQuest软件的理解&#xff0c;基本上可以找到关键路径&#xff0c;此文章主要对关键路径时序进行优化&#xff0c;使设计达到时序要求&#xff0c;以…...

LeetCode第332场周赛

2023.2.12LeetCode第332场周赛 6354. 找出数组的串联值 思路 双指针模拟&#xff0c;两个指针相遇的时候要特判 算法 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long ans 0;int i 0, j nums.size() - 1;while (i <…...

2023-2-12刷题情况

字母板上的路径 题目描述 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”]&#xff0c;如下所示。 我们可以按下面的指令规则行动…...

拉普拉斯矩阵

拉普拉斯算子 Δff(xi1,yj)f(xi−1,yj)f(xi,yj1)f(xi,yj−1)−4f(xi,yj)∑(k,l)∈N(i,j)(f(xk,yl)−f(xi,yj))\begin{aligned} \Delta f & f\left(x_{i1}, y_j\right) f\left(x_{i-1},y_j\right) f\left(x_i,y_{j1}\right)f\left(x_i,y_{j-1}\right) - 4f\left(x_i,y_j\r…...

Top-1错误率、Top-5错误率等常见的模型算法评估指标解析

Top-1 错误率&#xff1a;指预测输出的概率最高的类别与人工标注的类别相符的准确率&#xff0c;就是你预测的label取最后概率向量里面最大的那一个作为预测结果&#xff0c;如过你的预测结果中概率最大的那个分类正确&#xff0c;则预测正确&#xff0c;否则预测错误。比如预测…...

Urho3D 容器类型

Urho3D实现了自己的字符串类型和模板容器&#xff0c;而不是使用STL。其基本原理如下&#xff1a; 在某些情况下提高了性能&#xff0c;例如使用PODVector类时。保证字符串和容器的二进制大小&#xff0c;以允许例如嵌入Variant对象内。减少了编译时间。直接命名和实现&#x…...

C语言学习笔记(四): 循环结构程序设计

while语句 定义 While语句是C语言中的循环语句&#xff0c;它按条件循环执行语句&#xff0c;直到条件不满足为止 语法格式如下: while(condition) {//循环体内容; }使用实例 求123…100 include <stdio.h> int main(){int i 1, sum 0;while (i<100){sum i …...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi&#xff0c;还有多少人在用&#xff1f; 去年&#xff0c;月之暗面创始人杨植麟别提有多风光了。90后清华学霸&#xff0c;国产大模型六小虎之一&#xff0c;手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水&#xff0c;单月光是投流就花费2个亿。 疯…...