HashSet集合是如何做到不重复的?

这次我们了解一下关于HashSet集合如何做到重复的。(这次的文章改编于网上某篇文章,但是又加入了我对于HashSet集合的一些理解,望谅解!)
Java中关于HashSet添加自定义对象时,自定义类要重写equals方法和hashCode方法的前世今生...

先了解一下HashSet集合的基本情况:
据我所知HashSet集合是没有顺序,也不允许重复[对象的重复]。
对象的重复:指的就是在内存中,所在的内存编号一样的同一个对象。
内存编号指的就是哈希码(哈希码一般是类名和对象所在内存地址的十六进制数字表示 的组合)。

然后了解一下相关的知识:
现实生活中只要属性相同,我们就认为那是同一个对象。
计算机中比较同一个对象的方法不同[计算机使用内存地址,即哈希码]。
于是,就需要重写equals方法和hashCode方法来让程序的运行结果符合现实生活,不同的类对于equals方法和hashCode方法的要求不一样。
附:基本数据类型的实现类都已经重写了上面的两个方法。

技术实现原理:
当你利用HashSet创建一个对象时,在HashSet的构造方法中,先用hashCode方法计算出该对象的哈希码。
比较顺序以及原理
        (1).如果该对象哈希码与集合已存在对象的哈希码不一致,则该对象没有与其他对象重复,添加到集合中!
        (2).如果存在于该对象相同的哈希码,那么通过equals方法判断两个哈希码相同的对象是否为同一对象(判断的标准是:属性是否相同)
                1>.相同对象,不添加!
                2>.不同对象,添加!

这时有两个疑问:
1.为什么哈希码相同了还有可能是不同对象?
按照Object类的hashCode方法,是不可能返回两个相同的哈希码的。(哈希码唯一标志了对象)
Object类的hashCode方法返回的哈希码具有唯一性(地址唯一性),但是这样不能明确的确定两者是不是同一个对象。(这个逻辑就是:属性相同的对象被看作同一个对象。)
所以综上所述两个对象重复的标准:哈希码相同且属性相同。

2.为什么经过比较哈希码还需要借助equals方法判断?                       
为了让程序的运行逻辑符合现实生活,区分哈希码相同但不是同一个对象的对象。(自定义的类要你自己重写。)
                             
重写的原因是什么?
在现实中,不同的类对于equals方法和hashCode方法的要求不一样。

扫描二维码关注公众号,回复: 539651 查看本文章

一个自定义的类:

package LQJ.newer.a3;


public class person {
	private String name;

	public person(String name) {
		this.name = name;
	}

	//重写的hashCode方法
	@Override
	public int hashCode() {
		return name.hashCode();
	}
	//重写的equals方法
	@Override
	public boolean equals(Object obj) {
		if (this == obj){
			return true;
		}
		if (obj instanceof person){
			person p = (person) obj;
			return this.name.endsWith(p.name);
		}		
		return false;
	}
	//重写的toString方法
	@Override
	public String toString() {
		return name;
	}
	
}

 主类调用:

package LQJ.newer.a3;

import java.util.HashSet;
import java.util.Iterator;

public class HashSetMAIN {

	public static void main(String[] args) {
		HashSet<person> set = new HashSet<person>();
		set.add(new person("张三"));
		set.add(new person("王二"));
		set.add(new person("刘四"));
		set.add(new person("李武"));
		set.add(new person("剑皇"));
		
		set.add(new person("王二"));
		// 迭代器对象:用来对数据结构取数据的一个对象
		// 得到set的迭代器
		Iterator<person> iter = set.iterator();
		// 判断迭代器中能不能迭代出数据
		while (iter.hasNext()) {
			// 取出数据
			person s = iter.next();
			System.out.println(s.toString());
		}
	}
}

猜你喜欢

转载自lqj2711.iteye.com/blog/2344939