概述
今天用HashSet需要添加不重复的对象,虽然知道HashSet是无序,不能添加重复对象,但是一直不清楚他的两个元素重复的标准是什么。
查看HashSet的添加方法
可以看到只有简单的一句, return map.put(e,PARSENT) == null
. 也就是说。那么这个map
和 PARSENT
是什么呢? 看下图
可以看出来,这里的map 是一个 HashMap
PRESENT 是一个 Object
也就是说,我们添加的元素是作为一个 HashMap的key 来添加到map 中的。
那么就去看一下HashMap
的put
方法把。
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
这段代码标识了。 如果你添加的key的 hashCode值 和 你hashMap中已经存在的key 的hashCode 值相同 与 你添加的key 和 已经存在的key集合中 equals 方法 都返回 true
. 那么 HashMap 不再添加 你的这个 key value 值了。只会 返回 你原来这个 key
所对应的 value
描述有点不太好
既然知道了原理。那么我们给HashSet 添加自己定义的类的对象的时候,就只需要重写 hashCode 方法和 equals 方法,让类对象中全部相同的field返回一致的hashCode 和 equals 的时候 返回true 。下面举个例子
自定义一个Test类
暂时先不重写hashCode方法和equals方法
public class Test{
private String name;
private int age;
/** 省略getter setter
}
通过 main方法进行测试
public static void main(String[] args) {
HashSet<Test> set = new HashSet<>();
set.add(new Test("gss",1));
set.add(new Test("gss",1));
set.add(new Test("gss",1));
System.out.println(set);
}
打印 set的值
[com.dayaotex.zhdy.ws.Test@78da5318, com.dayaotex.zhdy.ws.Test@4848268a, com.dayaotex.zhdy.ws.Test@295bc68c]
可以看到三个都已经添加到HashSet 中了。那么我们重写HashCode 和 equals 方法试试看
添加了 hashcode 和 equals 方法的Test 类
package com.dayaotex.zhdy.ws;
public class Test{
private String name;
private int age;
// 省略getter setter 方法
@Override
public boolean equals(Object obj) {
if (obj instanceof Test){
Test test = (Test) obj;
return this.name == test.getName()&&this.age == test.getAge();
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode()+age;
}
}
再次运行 main 方法。 查看返回结果
[com.dayaotex.zhdy.ws.Test@19108]
现在添加到set 集合中只有 这一个对象了。