什么是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. NLP语言学基础

    不同的自然语言有不同的语法结构,因此需要对语言数据进行语法解析,才能让机器更准确地学到相应的模式.而语言不同于图像,数据标注工作需要有一定的语言学知识,因此数据的整理也相对更困难.下面以英语为例(别的 ...

  2. gh-ost工具在线改表过程的详细解析

    gh-ost,是github开源的一款在线修改MySQL表结构的工具https://github.com/github/gh-ost/,它不使用pt-osc的触发器机制,而是使用解析binlog来实现 ...

  3. Java线程:新特征-条件变量

    条件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量.但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往通过代码来赋予其含义.   这里的条 ...

  4. 七、FreeRTOS学习笔记-中断管理

    FreeRTOS学习笔记-中断管理 中断:让CPU打断正常运行的程序,转而去处理紧急的事件(程序) 中断执行机制,可简单概括为三步: 1.中断请求:外设产生中断请求(GPIO外部中断.定时器中断等) ...

  5. PC自动化之pywinauto

    官方文档: https://pywinauto.readthedocs.io/en/latest/contents.html [安装] pip install pywinauto [使用] from ...

  6. golang之JSON处理

    在强类型语言中,JSON 通常很难处理 -- JSON 类型有字符串.数字.字典和数组.如果你使用的语言是 javascript.python.ruby 或 PHP,那么 JSON 有一个很大的好处就 ...

  7. Tornado框架之基础(一)

    知识点 了解什么是Tornado框架 了解Tornado与Django的区别 Tornado的安装 了解Tornado的原理 掌握Tornado的基本写法 掌握Tornado的基本模块 tornado ...

  8. Educational Codeforces Round 77 (Rated for Div2)

    B - Obtain Two Zeroes 给定两个整数\(a,b\),你可以执行以下操作任意次:每次操作选择一个正整数\(x\),使得\(a:=a-x,b:=b-2x\)或者\(a:=a-2x,b: ...

  9. 使用nginx 解决开发过程中的跨域问题

    遇到的问题 在开发vue 前端程序时,我们会创建多个项目,比如用户管理为一个应用,系统管理为一个应用,这样多个应用势必需要开多个端口,这样问题就来了,我们在登录后会生成一个token,这个token我 ...

  10. Echarts 坐标轴

    1.坐标轴组件配置项总览 坐标轴分为x轴和y轴,操作这两个轴的字段分别为xAxis和yAxis var option = { xAxis:{ name:"月份", axisTick ...