HashSet集合存储自定义对象细节

来源:互联网 发布:郑州数据分析师工资 编辑:程序博客网 时间:2024/05/16 00:54

在说HashSet集合怎么存储自定义对象细节之前,先看看HashSet类的特点吧。

通过查阅API,发现HashSet集合:

1、  HashSet集合底层使用哈希表结构

2、  HashSet集合中的存储的元素是无序的

3、  因为继承了Set接口,所以不能存储重复元素

4、  允许存储null元素,但是只能有一个

5、 性能:查询元素和存储不重复元素的效率比较高

既然,HashSet集合底层使用哈希表,再来说说哈希表是什么个东西吧?

2. 哈希表

集合的底层使用哈希表。

所谓的哈希表其实底层还是使用数组,只是这个数组中存在一种算法:哈希算法。所以才称为哈希表(下图参考传智播客唐文杰老师)








HashSet
集合底层哈希表存储元素的过程:

1、 在向HashSet集合中存储元素时,会先拿要存储的元素和哈希算法结合,计算出哈希值(元素的存储位置)。

2、 判断计算出的存储位置上是否已经有元素存在了

有元素存在:拿要存储的元素和已经存在的元素进行equals比较

            equasl结果:相同 ,表示重复元素。不做存储操作

            equals结果:不相同, 继续计算新的存储位置(常用作法:拉链法)

拉链法:会使用当前存储位置和哈希算法继续计算新的存储位置,再判断新的存储位置上是否有元素存在(和之前方案类同)

没元素存在:直接把元素存到该位置上

到这里,大家有没有疑问,存储的元素怎么去和算法结合的呢?
笔者当初在此处也很疑惑,当我们向HashSet集合中添加元素时,使用add方法时,并没有看到算法,那么存储的元素怎么和算法结合的呢?
在这里我们思考下面两个问题

  思考:集合中只能存储什么类型的元素?  引用类型

       思考:引用类型的元素有父类吗?  最高父类是Object

对,你猜对了。在object 类中存在一个功能,可以用来计算哈希值

好了,说了那么多关于哈希表底层的内容,我们再言归正题,笔者通过一个案例来说明怎么才能存储自定义对象不重复呢?




package com.hmtest.demo;


public class Person {
private String name;
private int 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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}



public class HashSetTest {


public static void main(String[] args) {
// 创建HashSet集合对象
HashSet set = new HashSet();

//向集合中添加Person对象
set.add(new Person("马云",53));
set.add(new Person("刘强东",43));
set.add(new Person("李彦宏",40));
set.add(new Person("马化腾",41));
set.add(new Person("马化腾",41));
//遍历
for (Iterator it = set.iterator(); it.hasNext();) {
Person p = (Person) it.next();
//输出Person
System.out.println(p);
}
}
}

输出结果:

为什么以在程序执行后,还会出现重复的对象呢?

这是因为在向集合中存储元素时,拿Person对象和哈希算法结合计算出哈希值。而创建的Person对象不同,所以在和哈希算法计算时,也就产生不同的哈希值(没有调用equals方法判断是否相等)。


解决方案:1,让存储的元素使用同一个哈希值,就会调用equals方法比较

具体做法是:在Person类中重写Object类中的hashCode方法,添加如下代码:

public int hashCode(){

return 10;//全部返回相同的哈希值

}

2,在计算出相同的哈希值后,还会存在equals比较对象,产生对象不相同结果。所以还需要在Person中重写Object类中的equals方法。

具体做法如下:在Person类中重写Object类中equals方法(比较对象中的内容)

public boolean equals(Object obj){

//判断你是否为Person对象

if(!(obj instanceof Person)) throw new RuntimeException("类型不匹配!");


Person p = (Person) obj; //强制类型转换

return this.age = p.age&&this.name.equals(p.name);

}

也许你看到上面步骤会抓狂,请不要激动,eclipse会懂你的。。你只需要按照下面的方法,eclipse会为你自动生成

Shift+Alt+S>>>>选择Gerate hasCode()and equals()系统会自动帮你生成所需要重写的代码。
让我们再来看看结果吧,结果终于是我们想要的啦!无重复的元素啦




0 0
原创粉丝点击