什么是HashSet

在 Java 中,HashSet 是一个基于哈希表实现的集合类,它实现了 Set 接口

HashSet 的主要特点是:1,2

HashSet 的主要特点是

1,集合中的数据不能够重复

2,存储的数据是无序的(元素的存储顺序与插入顺序无关)

3,允许 null 值: 可以存储一个 null 元素(感觉这个不算)

HashSet 的常用方法

boolean add(e)向集合中添加元素。如果元素已存在,则返回 false。

boolean remove(Object o)从集合中移除指定元素。如果元素存在并成功移除,则返回 true。

boolean contains(Object o)检查集合中是否包含指定元素。如果存在,则返回 true。

int size() 返回集合中元素的数量。

boolean isEmpty()检查集合是否为空。如果为空,则返回 true。

void clear()清空集合中的所有元素。

Iterator iterator() 返回一个迭代器,用于遍历集合中的元素。

Object[] toArray() 将集合转换为数组。

hasSet存储为啥是无序的

hasSet 存储为啥数据不能够重复

hash存储是幂等性算法

也就是说:你给我一个A,计算出来的是2。

下次你再给一个A,计算出来的仍然是2。

这样的话,就会造成一个问题。

这个2要不要存储呢?

hasSet会丢弃第2个相同的值,因此存储的数据是不能够重复的。

存储数据是无序的

package part;
// HashSet在util这个包中,需要我们引入
import java.util.HashSet;
public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("赵6");
// 输出的来是: [赵6, 李四, 张三] 说明存储数据是无序的
System.out.println(setObject);
}
}

存储的数据是不会重复的

public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("张三");
// 输出的来是:
System.out.println(setObject);
}
}

HashSet如何修改数据

HashSet无法直接修改数据。

我们需要先把某一条要修改的数据删除掉。在新增我们想要的数据

package part;
// HashSet在util这个包中,需要我们引入
import java.util.HashSet; public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
// 把张三更改为张3,我们先删除然后再新增
setObject.remove("张三");
setObject.add("张3");
// 输出: [李四, 张3]
System.out.println(setObject);
}
}

增强 for循环(也称为 for-each 循环) 来遍历数据

package part;
// HashSet在util这个包中,需要我们引入
import java.util.HashSet;
public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 我们通过特殊for循环来遍历数据
for (Object o : setObject) {
System.out.println(o);
}
}
}

增强 for循环的语法

for (元素类型 变量名 : 数组或集合) {
// 循环体
// ps: 变量名是循环中的每一项
}

HashSet.add新增元素(如果元素已存在,则返回 false)

package part;
// HashSet在util这个包中,需要我们引入
import java.util.HashSet;
public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 输出的是 [李四, 张三, 王五]
System.out.println(setObject);
}
}

HashSet.addAll 将一个集合中的所有元素添加到另一个集合中

package part;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
ArrayList<Integer> listObject = new ArrayList();
listObject.add(1);
listObject.add(2);
LinkedList linkedListObject = new LinkedList();
linkedListObject.add("张三");
// 添加一个ArrayList集合对象
setObject.addAll(listObject);
// 添加一个LinkedList集合对象
setObject.addAll(linkedListObject);
// 输出的是: [1, 2, 张三]
System.out.println("setObject:" + setObject);
}
}

HashSet.toArray 将HashSet转化为数组

public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 将 HashSet 转换为数组
Object obj = setObject.toArray();
System.out.println(obj);
}
}

HashSet.size() 获取HashSet 的长度

public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 获取HashSet 的长度
int len = setObject.size();
System.out.println(len);
}
}

HashSet.clone 克隆

package part;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 克隆HashSet,相当于复制了一份。但是我们需要使用Object来声明
Object newSet = setObject.clone();
}
}

克隆 HashSet 可以不用Object来声明吗?

克隆 HashSet 可以不用 Object 来声明吗? 可以的。

那为啥克隆需要使用 Object来声明呢?

因为:clone() 方法的返回类型是 Object。所以我们需要使用Object来声明。

我们可以使用强制转化来处理就行

public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 克隆HashSet,相当于复制了一份。我们可以使用强制转化来解决这个问题的
HashSet newSet =(HashSet) setObject.clone();
}
}

HashSet.remove(被移除的对象)

要从 HashSet 中移除的对象。如果 HashSet 包含该对象,则会被移除。

返回值是一个布尔值

如果 HashSet 中包含指定的对象并且成功移除,则返回 true。

如果 HashSet 中不包含该对象,则返回 false。

public class Java01 {
public static void main(String[] args) {
HashSet setObject = new HashSet();
setObject.add("张三");
setObject.add("李四");
setObject.add("王五");
// 移除李四
Boolean delStatus = setObject.remove("李四");
// 输出的是true
System.out.println(delStatus);
}
}

ArrayList.remove根据传参不同,返回的类型不同

ArrayList arrList = new ArrayList();
arrList.add("嘿嘿01");
// 传参的是数字,返回的是被删除的数据
Object oldValue = arrList.remove(0);
public class Java01 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("A");
// 传参字符串,返回来的是布尔
Boolean flag = list.remove("A");
System.out.println(flag);
}
}

HashSet存储了相同的数据

package part;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; public class Java01 {
public static void main(String[] args) {
HashSet setList = new HashSet();
User u1 = new User();
User u2 = new User();
u1.id = "2025_01_30";
u1.name = "张三";
u2.id = "2025_01_30";
u2.name = "张三";
setList.add(u1);
setList.add(u2);
// 大家认为会输出什么呢?
// 输出的 [User [id=2025_01_30, name=张三], User [id=2025_01_30, name=张三]]
System.out.println(setList);
}
} class User{
String id;
String name;
// ctrl + o 就可以啦 现在我重写了 toString
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}

不是说:HashSet中的数据不能重复吗?

为啥会重复呢?

因为:这2个对象在内存中是不同的地址哈~。

所以HashSet会认为是不同的值。

内存中是不同的地址我们一般认为是 hashCode不同(这种说法不准确,但是方便我们理解)

ps: hashCode类似与内存中的地址

解释为啥存储了相同的数据


package part;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; public class Java01 {
public static void main(String[] args) {
HashSet setList = new HashSet();
User u1 = new User();
User u2 = new User();
u1.id = "2025_01_30";
u1.name = "张三";
u2.id = "2025_01_30";
u2.name = "张三";
setList.add(u1);
setList.add(u2);
// hashCode 我们可以理解为内存中的地址(这种说法不准确,但是方便我们理解)
System.out.println(u1.hashCode()); // 685325104
System.out.println(u2.hashCode()); // 460141958
// 我们发现这2个地址不同,就会认为是2个不同的对象,就会出现相同的数据
}
} class User{
String id;
String name;
// ctrl + o 就可以啦
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}

如何如果让一个对象的id和name相同,就让它识别为是同一个数据

如果让一个对象的id和name相同,就让它识别为是同一个数据呢?

是可以的。我们需要重写2个方法;hashCode 和 equals

因为: HashSet是在存储数据的时候,就是通过hashCode来操作的。

我们给定一个值(字符串), 通过操作得到存储到哪一个位置。

当然不同的值可能得到的存储位置是一样的。

如果出现这样的情况,他会去比较他们的equals。

如果相等,会把这个数据(后面这个新增的数据)丢弃,什么都不做。

如果不相等,这个时候他会使用链表它装在一起哈。

我们也可以从这里得出结论:HashSet的底层是:数组+链表的结构来进行存储数据的

重写hashCode 和 equals


package part;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; public class Java01 {
public static void main(String[] args) {
HashSet setList = new HashSet();
User u1 = new User();
User u2 = new User();
u1.id = 2025;
u1.name = "张三";
u2.id = 2025;
u2.name = "张三";
setList.add(u1);
setList.add(u2);
// [User [id=2025, name=张三]] 现在数据就不会重复了
System.out.println(setList);
}
} class User{
int id;
String name;
// 重写方法的快捷键 ctrl+o
@Override
// 类似与我们的内存地址,我们使用id来判断
public int hashCode() {
return id;
} @Override
// 判断2个对象的属性是否完全相同
public boolean equals(Object obj) {
if(obj instanceof User) {
//因为这个对象是User类型的,我们可以使用强制转换
User u = (User)obj;
//判断对象的属性是否相同,这里为啥使用equals,等会回说一下
if(u.id==this.id && u.name.equals(this.name)) {
return true;
}else{
return false;
}
}else{
// 如果不是,直接返回false
return false;
}
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}

HashSet的底层是:数组+链表的结构来进行存储数据的

== 和 equals的区别

1,当使用 == 比较基本数据类型,它比较的是两个变量的值是否相等。

2,当使用 == 比较引用数据类型(如对象)时,它比较的是对象的内存地址是否相等,即它们是否引用同一内存地址。

3,equals是Object类中的一个方法,用于比较同一类的两个对象的内容是否相等。

equals的比较逻辑

equals方法首先检查两个对象是否为同一类的实例(即类是否相等)。

如果不属于同一类,则对象肯定不相等。

如果类相等,equals方法将逐一比较两个对象的字段或属性,以确定它们是否相等。

尾声

准备开始学习java了。

今天学习的第三天,每天都会发文章,我要卷起来。

请小伙伴们监督我,奥利给

java中的HashSet的更多相关文章

  1. java中的hashSet和Treeset的分析

    hashset中的元素 treeset中的元素要实现comparable接口

  2. Java中的HashSet和TreeSet

    1:Set集合(理解) (1)Set集合的特点 无序,唯一 (2)HashSet集合(掌握) A:底层数据结构是哈希表(是一个元素为链表的数组) B:哈希表底层依赖两个方法:hashCode()和eq ...

  3. java中集合类HashSet、ArrayList、LinkedList总结

    [HashSet] 1. HashSet存储不能够存储相同的元素,元素是否相同的判断:重写元素的equals方法.equals方法和hashCode方法必须兼容,如:equals方法判断的是用户的名字 ...

  4. Java 中的 HashSet,内部是如何工作的?

    HashSet 的内部采用 HashMap 来实现.由于 Map 需要 key 和 value,所以 所有 key 的都有一个默认 value.类似于 HashMap,HashSet 不允许重复的 k ...

  5. java中使用hashSet的特性,判断数组是否有重复值

    public static boolean cheakRepeat(int[] array){ HashSet<Integer> hashSet = new HashSet<Inte ...

  6. java 中遍历hashmap 和hashset 的方法

    一.java中遍历hashmap:    for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {     String ...

  7. Java中如何克隆集合——ArrayList和HashSet深拷贝

    编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...

  8. java中HashSet详解(转)

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  9. java中HashSet详解

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  10. java集合(4)- java中HashSet详解

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

随机推荐

  1. dotnet学习笔记-专题06-过滤器和中间件-01

    1. 基本概念 在ASP.NET Core中,中间件和过滤器都是处理HTTP请求的重要组件,但它们在应用中的位置.作用范围以及使用方式有所不同. 1.1 中间件和过滤器的区别 1.1.1 中间件 位置 ...

  2. 简单端口映射、转发、重定向工具之Rinetd

    ◆一.概述 Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具.将 TCP 连接从一个 IP 地址和端口重定向到另一个.它处理文件中/etc/rinetd ...

  3. Django之form表单的数据验证

    1.先导入forms模块 from django import forms 2.创建模板的类 class loginform(forms.Form): # 2.模板中的元素 name = forms. ...

  4. php-fpm常见错误

    1. WARNING: Nothing matches the include pattern '/usr/local/php7/etc/php-fpm.d/*.conf' # cd /usr/loc ...

  5. openwrt交换机配置命令-swconfig

    swconfig swconfig 是交换接口 (switch) 配置命令. 交换机是二层设备,是我们用来配置vlan的必备利器. 使用swconfig list可以列出当前可用的 SWITCH 设备 ...

  6. WebP图片使用踩坑

    前情 WebP是一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式,最初在2010年发布,目标是减少文件大小,相较于传统的 PNG.JPG,甚至是动图 GIF 的格式,WebP 比它们的空间更 ...

  7. [.NET Blog] .NET Aspire 测试入门

    https://devblogs.microsoft.com/dotnet/getting-started-with-testing-and-dotnet-aspire/ 自动化测试是软件开发的重要一 ...

  8. OpenType 字体文件组织结构

    OpenType 字体文件结构 OpenType 字体的组织 https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organi ...

  9. TypeNameExtractor could not be found

    TypeNameExtractor could not be foundException 一.注意: 如果项目中使用了 knif4j或swagger (knif4j内核中就使用了swagger) 项 ...

  10. Qt数据库应用20-csv文件转xls

    一.前言 最近又多了个需求就是将csv格式的文件转xls,需求一个接着一个,还好都是真实的需求,而且都是有用的需求,并不是不靠谱的需求,不靠谱的需求就比如程序自动识别手机壳颜色自动换背景颜色或者边框颜 ...