当前位置: 首页 > 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 …...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...