您的位置:首页 > 职场人生

黑马程序员_日记42_HashSet自定义对象去重练习

2015-04-15 00:00 477 查看
 ——- android培训java培训、期待与您交流! ———-

往hashSet集合中存入自定对象

姓名和年龄相同为同一个人,重复元素。

思路:

1 把数据存入Person,建立Person类

2 把Person对象存入HashSet,建立HashSet集

先运行一遍,观察运行结果,进行分析。

import java.util.*;
//1 把数据存入Person,建立Person类
class Person
{
private String name;//姓名
private int age;//年龄

Person(String name,int age)
{
this.name = name;
this.age = age;
}

public void setName(String name)
{
this.name = name;
}

public String getName()
{
return name;
}

public void setAge(int age)
{
this.age =age;
}

public int getAge()
{
return age;
}
}

//主类
class HashSetTest
{
public static void main(String[] args)
{
//1 创建HashSet集
HashSet hs = new HashSet();

//2 把Person对象存入集合
hs.add(new Person("Jack",20));
hs.add(new Person("Jack",20));
hs.add(new Person("Tom",18));
hs.add(new Person("Tom",18));
hs.add(new Person("Mike",19));
hs.add(new Person("Jane",26));

//3 取出元素
for(Iterator it = hs.iterator(); it.hasNext(); )
{
//强制转换为Person
Person p = (Person)it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}




运行结果为:

Tom—18

Jack—20

Jane—26

Jack—20

Tom—18

Mike—19

观察发现,元素并没有去重,这是为什么呢??

这是因为HashSet调用了Object中的hashCode方法!

程序是这样工作的:

JVM调用hashCode方法计算了元素的地址值,

如果地址值不冲突,则存入HashSet。

而上面调用add方法时,每一个Person对象都是在内存新开辟一块空间,

地址值都是不一样的,不可能发生地址冲突,所以都成功的存入了HashSet。

所以,首先必须要做的事就是在Person类中覆盖Object的hashCode方法!

那么到底该怎么重写呢?

这里提供两种方式:

方式一:

public int hashCode()
{
return 60;
}


方式二:

public int hashCode()
{
return name.hashCode()+age*37;
}


需要解释的地方:

使用方式一,程序是这样走的:

每一个对象返回的哈希值都一样,发生了冲突,

那么它们就以链表的方式链接存储,

这样存入的元素越多,效率就越低,

为了减少比较次数,

就设计到了hashCode()的算法优化能力!

这里采用了简单的处理,如方式二。

使用方式二:

name是String类型的,String类已经覆盖了hashCode()方法,

所以,可以通过调用得到name的哈希值。

而age*37是为了减少哈希值相等的几率,

减少计算量,提高效率!

同时应该考虑到int的取值范围,应当用“+”求和,

而不是直接把name的哈希值乘以age。

接着上面的思路:

3 重写Person类中的hashCode方法

运行程序,观察结果。

发现仍然有重复的元素,这是为什么呢?

这是因为在判断元素的哈希值之后,

如果哈希值相同,会调用equals方法判断内容是否一样。

这就要求:

4 重写equals方法.

import java.util.*;
//1 把数据存入Person,建立Person类
class Person
{
private String name;//姓名
private int age;//年龄

Person(String name,int age)
{
this.name = name;
this.age = age;
}

public void setName(String name)
{
this.name = name;
}

public String getName()
{
return name;
}

public void setAge(int age)
{
this.age =age;
}

public int getAge()
{
return age;
}

//重写hashCode方法
public int hashCode() { return name.hashCode()+age*37; }

//重写equals方法
public boolean equals(Object obj)
{
//强制转换Person类型
Person p = (Person)obj;

//判断是否为同一个人
return this.getName().equals(p.getName()) && this.getAge()==p.getAge();
}
}

//主类
class HashSetTest
{
public static void main(String[] args)
{
//1 创建HashSet集
HashSet hs = new HashSet();

//2 把Person对象存入集合
hs.add(new Person("Jack",20));
hs.add(new Person("Jack",20));
hs.add(new Person("Tom",18));
hs.add(new Person("Tom",18));
hs.add(new Person("Mike",19));
hs.add(new Person("Jane",26));

//3 取出元素
for(Iterator it = hs.iterator(); it.hasNext(); )
{
//强制转换为Person
Person p = (Person)it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}




运行结果:

Tom—18

Jane—26

Jack—20

Mike—19

说明已经成功去重了,HashSet中已经不存在同名同年龄的人了!

总结:在HashSet中,存入元素是先判断哈希值是否一样,再判断内容是否一样!

hashset为了保证元素唯一:

1 如果元素哈希值相同,就判断equals是否为true;

2 如果哈希值不相同,不会调用equals方法。

此外,contains()和remove()等操作,HashSet都是依赖hashCode()和equals方法。

所以在类中必须重写这两个方法,才能保证元素唯一!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hashset person 去重
相关文章推荐