黑马程序员_日记42_HashSet自定义对象去重练习
2015-04-15 00:00
477 查看
——- android培训、java培训、期待与您交流! ———-
往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。
思路:
1 把数据存入Person,建立Person类
2 把Person对象存入HashSet,建立HashSet集
先运行一遍,观察运行结果,进行分析。
![](https://img-blog.csdn.net/20150414235938780)
运行结果为:
Tom—18
Jack—20
Jane—26
Jack—20
Tom—18
Mike—19
观察发现,元素并没有去重,这是为什么呢??
这是因为HashSet调用了Object中的hashCode方法!
程序是这样工作的:
JVM调用hashCode方法计算了元素的地址值,
如果地址值不冲突,则存入HashSet。
而上面调用add方法时,每一个Person对象都是在内存新开辟一块空间,
地址值都是不一样的,不可能发生地址冲突,所以都成功的存入了HashSet。
所以,首先必须要做的事就是在Person类中覆盖Object的hashCode方法!
那么到底该怎么重写呢?
这里提供两种方式:
方式一:
方式二:
需要解释的地方:
使用方式一,程序是这样走的:
每一个对象返回的哈希值都一样,发生了冲突,
那么它们就以链表的方式链接存储,
这样存入的元素越多,效率就越低,
为了减少比较次数,
就设计到了hashCode()的算法优化能力!
这里采用了简单的处理,如方式二。
使用方式二:
name是String类型的,String类已经覆盖了hashCode()方法,
所以,可以通过调用得到name的哈希值。
而age*37是为了减少哈希值相等的几率,
减少计算量,提高效率!
同时应该考虑到int的取值范围,应当用“+”求和,
而不是直接把name的哈希值乘以age。
接着上面的思路:
3 重写Person类中的hashCode方法
运行程序,观察结果。
发现仍然有重复的元素,这是为什么呢?
这是因为在判断元素的哈希值之后,
如果哈希值相同,会调用equals方法判断内容是否一样。
这就要求:
4 重写equals方法.
![](https://img-blog.csdn.net/20150414235908800)
运行结果:
Tom—18
Jane—26
Jack—20
Mike—19
说明已经成功去重了,HashSet中已经不存在同名同年龄的人了!
总结:在HashSet中,存入元素是先判断哈希值是否一样,再判断内容是否一样!
hashset为了保证元素唯一:
1 如果元素哈希值相同,就判断equals是否为true;
2 如果哈希值不相同,不会调用equals方法。
此外,contains()和remove()等操作,HashSet都是依赖hashCode()和equals方法。
所以在类中必须重写这两个方法,才能保证元素唯一!
往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方法。
所以在类中必须重写这两个方法,才能保证元素唯一!
相关文章推荐
- 黑马程序员_日记58_HashMap自定义对象存取练习
- 黑马程序员_日记59_TreeMap自定义对象练习
- 黑马程序员_Arraylist、HashSet存储自定义对象的方式
- 集合框架_HashSet存储自定义对象并遍历练习
- JAVA之旅(二十)—HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习
- JAVA之旅(二十)—HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习
- 黑马程序员—集合将自定义对象作为元素存储到ArrayList集合中,并去除重复元素。 比如:存人对象。同姓名同年龄,视为同一个人,为重复元素。
- [置顶] HashSet保存自定义不重复对象
- [置顶] HashSet保存自定义不重复对象
- 黑马程序员-HashSet讲解学习日记
- 黑马程序员-IO流(对象序列化、RandomAccessFile 类、字符编码、综合练习)
- java小练习,往ArrayList中存自定义的对象
- java练习3,去除容器中自定义的重复对象
- 黑马程序员 Java练习-自定义图形化界面模拟浏览器访问Tomcat服务器
- 【练习】面向对象系列(005)——在自定义窗口中画矩形、直线、椭圆、涂鸦
- 黑马程序员——学习日记之--常见的其他对象
- Javascript(二)-09-(常见对象-Array-练习-自定义功能)
- HashSet存储自定义对象如何保证唯一性
- TreeSet存储自定义对象并遍历练习2(按照姓名的长度排序)
- [置顶] HashSet保存自定义不重复对象