Java基础知识点之HashSet
创始人
2025-06-01 10:12:30

HashSet是一个具有唯一元素的二叉树集合,同时HashSet是Set接口的一个实现类(HashSet实现了Set的接口),它具有Set的特点。
Set的特点有:不可重复,元素无顺序,没有带索引的方法(因此不能使用普通for循环来遍历,也不能通过索引来获取或删除Set集合中的元素值)。

HashSet的特点有:底层数据结构是哈希表;对集合的迭代顺序不作任何保证,也就是说不保证存储和取出元素顺序一致(即元素无顺序);没有带索引的方法(因此不能使用普通for循环来遍历,也不能通过索引来获取或删除HashSet集合中的元素值);不可重复。

接下来我们将从HashSet的四个特点并结合代码来学习HashSet。(由于HashSet没有带索引的方法,因此HashSet的第四个特点只能使用forEach语句与Iterator迭代器来实现HashSet的遍历)

注意:同样的,HashSet与TreeSet均是Set接口的一个实现类,因此HashSet的默认数据类型也是Object类,理论上我们可以通过add()方法来添加任意数据类型,但是如果我们这样子做,当我们进行遍历输出的时候就会遇到麻烦!!!因此我们在使用HashSet的时候,请使用泛型来约束数据类型!!!

由于哈希表同样也是一个很重要的知识点,因此在这里我们先跳过它,先来讲HashSet的后面三个特点。之后笔者会单独为哈希表写一篇知识点博客。

一、不可重复

String类型的HashSet

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//使用add()方法来添加数据hashset.add("bb");hashset.add("aa");hashset.add("cc");hashset.add("ee");hashset.add("aaa");hashset.add("bb");//打印System.out.println(hashset);}

运行结果(重复的bb元素被筛掉)
在这里插入图片描述


二、使用forEach语句和Iterator迭代器遍历输出HashSet

forEach语句遍历输出HashSet

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//使用add()方法来添加数据hashset.add("bb");hashset.add("aa");hashset.add("cc");hashset.add("ee");hashset.add("aaa");hashset.add("bb");//在此我们使用forEach来遍历HashSet//String是hashset的数据类型,我们将hashset的数据存入str(此名字你可以自定义)中并输出for(String str:hashset){System.out.println(str);}}

运行结果(重复的bb元素被筛掉)
在这里插入图片描述


Iterator迭代器遍历输出HashSet

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//使用add()方法来添加数据hashset.add("bb");hashset.add("aa");hashset.add("cc");hashset.add("ee");hashset.add("aaa");hashset.add("bb");//创建迭代器对象,由于hashset的类型是String类型,因此迭代器的数据类型也是StringIterator iterator=hashset.iterator();//判断该位置是否有值,iterator.hasNext()它会查看我们当前位置是否存在元素,存在元素返回true,不存在元素返回falsewhile(iterator.hasNext()){//获取该位置的元素值,iterator.next()它会取得我们目前位置的元素,然后指针后移System.out.println(iterator.next());}}

运行结果(重复的bb元素被筛掉)
在这里插入图片描述


三、不保证存储和取出元素顺序一致

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//使用add()方法来添加数据hashset.add("zhangsan");hashset.add("wangwu");hashset.add("lisi");hashset.add("aa");hashset.add("aaa");hashset.add("aa");//打印System.out.println(hashset);}

运行结果(重复的aa元素被筛掉),我们发现我们输出的顺序与插入的顺序是不一致的,因此HashSet不保证存储和取出元素顺序一致。
在这里插入图片描述


四、案例-HashSet集合储存学生对象并遍历

原始Student类

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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

HsahSet的main()方法

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//使用add()方法来添加数据hashset.add(new Student("zhangsan",18));hashset.add(new Student("zhangsan",18));hashset.add(new Student("lisi",18));hashset.add(new Student("wangwu",20));hashset.add(new Student("chenliu",20));//创建迭代器对象,由于hashset的类型是Student类型,因此迭代器的数据类型也是StudentIterator iterator=hashset.iterator();//判断该位置是否有值,iterator.hasNext()它会查看我们当前位置是否存在元素,存在元素返回true,不存在元素返回falsewhile(iterator.hasNext()){//获取该位置的元素值,iterator.next()它会取得我们目前位置的元素,然后指针后移System.out.println(iterator.next());}}

在main()方法中,我们插入两个相同的对象,我们查看重复值是否会被筛掉
运行结果(我们发现他们两个都输出了,我们认为的重复值并没有被筛掉)
在这里插入图片描述


那么这是为什么呢?其实我们在元素进行比较的时候,计算机并不是通过比较他们的对象值来判定他们是否不同,而是通过比较他们存储的内存地址来比较他们是否不同,那么我们接下来分别输出它们的HashCode()的值(对象存储的内存空间的int类型数值)

hashCode的main()方法

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//创建Student对象Student s1=new Student("zhangsan",18);Student s2=new Student("zhangsan",18);//打印hashcode值,观察他们的内存地址是否相同System.out.println(s1.hashCode());System.out.println(s2.hashCode());}

运行结果(我们发现他们两个的hashCode值是不同的,这就是为什么计算机不认为他们是一样的原因
在这里插入图片描述


那么我们如何使得计算机知道他们两个是相同的呢,这就需要我们在Student类中重写HashCode()方法

改进Student类
笔者用的编译器是IDEA,在IDEA的Student类中右键--->Generate...
在这里插入图片描述


选中equals() and hashCode()
在这里插入图片描述


点击Next
在这里插入图片描述


点击Next
在这里插入图片描述


点击Next
在这里插入图片描述


点击Finish
在这里插入图片描述


重写后的Student类

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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic 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 && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}

hashCode的main()方法

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//创建Student对象Student s1=new Student("zhangsan",18);Student s2=new Student("zhangsan",18);//打印hashcode值,观察他们的内存地址是否相同System.out.println(s1.hashCode());System.out.println(s2.hashCode());}

运行结果如下:(我们可以看到此时计算机已然认为s1与s2是相同的)
在这里插入图片描述

运行如下main()方法

public static void main(String[] args) {//若要使用HashSet,我们需要导入import java.util.HashSet;//我们使用泛型来约束HashSet的数据类型为String数据类型HashSet hashset=new HashSet<>();//创建Student对象Student s1=new Student("zhangsan",18);Student s2=new Student("zhangsan",18);//添加对象hashset.add(s1);hashset.add(s1);//1:普通打印System.out.println(hashset);System.out.println("====华丽的分割线====");//2:forEach打印for(Student stu:hashset){System.out.println(stu);}System.out.println("====华丽的分割线====");//3:Iterator迭代器打印Iterator iterator=hashset.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}

运行结果如下:(我们可以看到此时计算机已然认为s1与s2是相同的,并且筛掉重复值)
在这里插入图片描述

OK!!!结束!!!

相关内容

热门资讯

【文化中国行】“圈”出幸福感!... (来源:工人日报) 阅读提示 近年来,嘉兴市总工会以全总“559”部署和省总工会“137...
特色养殖“驮”起增收梦 投喂黑驴。本报记者 栾雨嘉 摄本报记者 栾雨嘉12月12日,黄南藏族自治州尖扎县措周乡俄什加村的肉驴...
内蒙古粮食产量达840.7亿斤 (来源:内蒙古日报)转自:内蒙古日报本报12月13日讯  (记者  韩雪茹)据12月12日国家统计局...
北疆楷模黄启东先进事迹报告会举... (来源:内蒙古日报)转自:内蒙古日报本报呼和浩特12月13日讯  (记者  皇甫秀玲)12月11日,...
全球最大储能电站在巴彦淖尔投运 (来源:内蒙古日报)转自:内蒙古日报本报巴彦淖尔12月13日电  (记者  薄金凤)12月12日,内...