Set集合中如何实现不重复?
Set集合是Collection的子类集合,属于单列集合
其特点及使不允许重复和不保证输出顺序,在此探讨一下其实现不重复的方法
以以下代码为例
public static void main(String[] args) {
method2();
}
public static void method2() {
Set set = new HashSet();
set.add(new User(1,"东北平原"));//每次创建对象,都会运行一个hashcode
set.add(new User(2,"华北平原"));
set.add(new User(3,"长江中下游平原"));
set.add(new User(4,"关中平原"));
set.add(new User(2,"华北平原"));
System.out.println(set);
}
public class User {
//地区编号
private int id;
//地区名字
private String name;
private User() {
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
System.out.println("-hashcode 默认的-");
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
System.out.println("-equals 默认的-");
return super.equals(obj);
}
以上代码的输出结果是
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
[User [id=2, name=华北平原], User [id=2, name=华北平原], User [id=3, name=长江中下游平原], User [id=4, name=关中平原], User [id=1, name=东北平原]]
我们可以从中发现每次创建一个对象之后,系统会先运行hashCode()进行地址的比较
所以我们进行修改
@Override
public int hashCode() {
System.out.println("-hashcode 默认的-");
return 1;//设定一个固定值从而让所有的对象的地址相同
}
再次运行主程序
-hashcode 默认的-
-hashcode 默认的-
-equals 默认的-
-hashcode 默认的-
-equals 默认的-
-equals 默认的-
-hashcode 默认的-
-equals 默认的-
-equals 默认的-
-equals 默认的-
-hashcode 默认的-
-equals 默认的-
-equals 默认的-
-equals 默认的-
-equals 默认的-
[User [id=1, name=东北平原], User [id=2, name=华北平原], User [id=3, name=长江中下游平原], User [id=4, name=关中平原], User [id=2, name=华北平原]]
我们可以发现,如果在所有的对象的地址相同的情况下,程序就会运行 equals(Object obj)对值进行对比。先进来两个对象,然后运行equals对两个对象进行对比,然后再进来一个对象,将这个对象和之前的两个对象再进行对比…
最后我们做出以下修改
@Override
public int hashCode() {
System.out.println("-hashcode 默认的-");
//return 1;//如果使用固定值,所有的对象地址相同,会造成哈希冲突
//降低哈希冲突
return this.id + this.name.hashCode();//只要地区代号和名字的哈希值不同就会识别为不同的地址
}
@Override
public boolean equals(Object obj) {
System.out.println("-equals 默认的-");
User user = (User)obj;
int temp = this.id - user.id;
if(temp == 0) {//地区编号相同的时候才去比较名字
return this.name.equals(user.name);
}
return false;
}
这种情况下,程序就会先运行hashCode()对数据的地址进行判断,只要地区代号和名字的哈希值不同就会识别为不同的地址。而如果地址相同,则会运行 equals(Object obj),对地区编号和名字进行对比。正是使用这种方法,set集合保证了元素的不重复
结果如下
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
-hashcode 默认的-
-equals 默认的-
[User [id=3, name=长江中下游平原], User [id=2, name=华北平原], User [id=1, name=东北平原], User [id=4, name=关中平原]]