java中set集合的重复验证机制

本文深入探讨了Java中Set集合的工作原理,特别是如何通过hashCode和equals方法判断元素重复,以及如何正确实现这两个方法以确保集合行为符合预期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java中set集合的使用非常广泛,这跟它存储的特性是有极大关系的。set集合拥有着与list集合不同的性质。
我们知道,set集合很重要的一个特性,是不允许存储重复的元素。那么,这究竟是怎么验证的呢。在之前的资料查询中,有这样一个说法,set集合进行插入的时候,会调用对象的equals方法,判断元素是否相同,若equals方法返回为true,则认为元素重复,不允许插入。于是我进行了代码验证。
我们一起来看下面的代码:

		Student s1=new Student("zhangsan","shandong","22");
		Student s2=new Student("zhangsan","shandong","22");
		Student s3=new Student("zhangsan","shandong","22");
		
		Set set=new HashSet();
		set.add(s1);
		set.add(s2);
		set.add(s3);
		System.out.println(set.size()); //输出为3

根据上面的例子我们可以发现,s1,s2,s3的属性完全相同,equals方法的返回值均为true,按照我们之前的预期,set应该只能插入一个元素。但在进行set的添加操作时,将三个对象都插入进了set集合中。我们发现关于equals方法的假设失败了。于是我又查阅了相关资料,发现set调用equals方法验证没有问题,但是有个前提条件。正确的验证流程应该是:
比较对象的hashCode是否相同,若相同,再进行equals方法的判断,true认为元素重复,反之元素不重复。若hashCode不相同,则直接返回元素不重复并将元素插入。
输出一下上面三个对象的hashCode发现:

		System.out.println(s1.hashCode());//658004038
		System.out.println(s2.hashCode());//1680568263
		System.out.println(s3.hashCode());//1605870897

s1,s2,s3的hashCode返回值不同,所以才会直接将三个元素插入进了set集合中。为了继续验证,我重写了Student的hashCode()方法,而后输出结果如下图:

	@Override
	public int hashCode(){
		return name.hashCode();
	}
	

在这里插入图片描述

此时,s1,s2,s3的hashCode相同,且equals方法返回为True,所以set判定元素重复,拒绝了后面两个对象的插入。

<think>好的,用户想要寻找Java中关于Set集合的经典练习题目,并且希望有示例代码。我需要根据用户提供的引用内容来组织答案。首先,查看用户提供的三个引用内容。 引用[1]提到Set用于存储不重复的元素,是高频知识点,涉及基础知识、实现类和应用场景。引用[3]则提供了一个具体的例子,使用TreeSet去重并按降序排列数组。这说明可能用户需要类似的实际代码示例。 接下来,我需要整理常见的Set习题类型。比如去重、集合运算、与其他集合转换、查找元素等。每个题目需要给出问题描述、解决思路和示例代码,并确保代码符合用户提供的引用中的例子格式,比如使用TreeSet和Collections.reverseOrder()。 然后,检查用户提供的引用中的代码是否符合Java语法,例如引用[3]中的代码是否正确。用户提供的示例代码使用了TreeSet和reverseOrder()来降序排列,这可以作为参考。 另外,用户可能希望这些练习题能覆盖不同的Set实现类,如HashSet、LinkedHashSet、TreeSet,以及它们的不同特性。例如,HashSet的无序性,TreeSet的排序功能,LinkedHashSet的插入顺序保持。 需要确保每个习题都有对应的代码示例,并且代码正确无误。例如,求交集、并集、差集等操作,可以通过addAll、retainAll、removeAll等方法实现。 还要注意引用文献的正确标注,例如在提到去重和排序时,引用[3]中的例子,并在适当的位置添加引用标记[^3]。 最后,生成相关问题,确保问题与Set集合的应用、性能、实现类比较等相关,帮助用户进一步深入学习。</think>### Java Set集合经典习题及示例代码 #### 1. 基础去重与排序 **问题**:给定一个整数数组,去除重复元素并按降序排列。 **解决思路**:利用`TreeSet`的自动去重和排序特性,通过`Collections.reverseOrder()`实现降序。 **示例代码**(引用自): ```java import java.util.*; public class Main { public static void main(String[] args) { Integer[] arr = {1, 2, 2, 3, 3, 4, 5, 6}; TreeSet<Integer> set = new TreeSet<>(Collections.reverseOrder()); set.addAll(Arrays.asList(arr)); System.out.println(set); // 输出 [6, 5, 4, 3, 2, 1] } } ``` #### 2. 集合运算(交集、并集、差集) **问题**:给定两个集合,求它们的交集、并集和差集。 **解决思路**:通过`retainAll`(交集)、`addAll`(并集)、`removeAll`(差集)实现。 **示例代码**: ```java Set<Integer> setA = new HashSet<>(Arrays.asList(1, 2, 3)); Set<Integer> setB = new HashSet<>(Arrays.asList(2, 3, 4)); // 交集 Set<Integer> intersection = new HashSet<>(setA); intersection.retainAll(setB); // 结果 [2, 3] // 并集 Set<Integer> union = new HashSet<>(setA); union.addAll(setB); // 结果 [1, 2, 3, 4] // 差集(A - B) Set<Integer> difference = new HashSet<>(setA); difference.removeAll(setB); // 结果 [1] ``` #### 3. 元素唯一性验证 **问题**:验证一个列表是否包含重复元素。 **解决思路**:比较列表长度与转换为`Set`后的长度。 **示例代码**: ```java List<Integer> list = Arrays.asList(1, 2, 3, 2); Set<Integer> set = new HashSet<>(list); boolean hasDuplicates = list.size() != set.size(); // 返回 true ``` #### 4. 实现自定义对象的去重 **问题**:自定义`Student`类(含`id`和`name`),要求根据`id`去重。 **解决思路**:重写`equals()`和`hashCode()`方法。 **示例代码**: ```java class Student { private int id; private String name; @Override public boolean equals(Object o) { return o instanceof Student && this.id == ((Student) o).id; } @Override public int hashCode() { return Objects.hash(id); } } // 使用示例 Set<Student> students = new HashSet<>(); students.add(new Student(1, "Alice")); students.add(new Student(1, "Alice")); // 不会被添加 ``` #### 5. 统计文本中不同单词数量 **问题**:读取一段文本,统计其中不同单词的数量。 **解决思路**:利用`HashSet`自动去重的特性。 **示例代码**: ```java String text = "apple banana apple orange banana"; Set<String> words = new HashSet<>(Arrays.asList(text.split(" "))); System.out.println(words.size()); // 输出 3 ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值