package en.itcast.demain;
public class Student {//自定义的学生类
private int age;
private String name;
public Student() {
super();
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 覆盖hashCode方法。根据对象自身的特点定义哈希值。
*/
@Override
public int hashCode() {
final int NUMBER = 36;
return this.name.hashCode() + this.age*NUMBER;
/**
* 4.在学生类中定义的hashCode方法中,由于学生年龄相仿的人有许多,会造成多次hash值冲突,导致调用过多的equals方法,
* 为此,应该改进hashCode方法。
* 可利用String中的hashCode方法输出字符串的哈希值,再加上原来的age,作为返回的hash值,为此,hash值冲突就会减少。
* 5.进一步减少hash值冲突,我可以在age后面乘以一个值--->原理:
* eg:
* name.hashCode() = 40,age = 20;
* name.hashCode() = 20,age = 40;
* 以上又会造成返回hash值冲突,当给age乘以一个数时,hash值冲突的概率会进一步减少。
*/
}
/**
* 需要定义对象自身判断内容相同的依据。
*/
@Override
public boolean equals(Object obj) {
System.out.println(this+"..."+obj);//查看生成对象时是如何调用equals方法
if(this == obj) {
return true;
}
if(!(obj instanceof Student)) {
throw new ClassCastException("类型错误");
}
Student student = (Student)obj;//强转:即所谓的向下转型
return this.name.equals(student.name)&&this.age == student.age;
}
}
package en.itcast.set.demo;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import en.itcast.demain.Student;
public class HashSetTest {//测试类
public static void main(String[] args) {
/*
* 需求:往HashSet中存储学生对象(姓名,年龄)。同姓名,同年龄视为同一个人,不存。
* 1.描述学生
* 2.定义容器
* 3.将学生存储到容器
*
*/
//1.创建容器对象
Set set = new HashSet<>();
//2.将学生存储到容器
/**
* 按照道理说:将同一个对象存入HashSet容器中,由于不允许存入重复元素,输出不会有重复元素
* 可输出事与愿违,原因出在何处?
* because:因为Student对象继承了Object对象中hashCode方法,使得创建每一个对象是调用hashCode()方法,
* 生存了不同的hash值,而容器中add方法是根据hash值来存储对象的,所以虽然是同一个对象,但是对应不同的hash值,
* 自然可以存入其中。
*
* 解决:
* 1.需要根据学生对象自身的特点来定义哈希值。
* 所以就要覆盖hashCode方法,我在Studnet类中是依据年龄返回哈希值的,然这不足以区分相同对象,因为同一年龄的对象有很多。
* 2.为此,就要利用针对同一个hash值冲突的解决办法,也就是重写equals方法,对每一个对象内容进行判断,至此可达到区分同一个对象的效果
* 3.注意:为什么之前存入相同字符串到HashSet容器中存不进去,应为String类有自己的hashCode方法,没有调用Object中hashCode方法,
* 自然区分了同一个字符串对应同一个哈希值。
* 4.在学生类中定义的hashCode方法中,由于学生年龄相仿的人有许多,会造成多次hash值冲突,导致调用过多的equals方法,
* 为此,应该改进hashCode方法。
* 可利用String中的hashCode方法输出字符串的哈希值,再加上原来的age,作为返回的hash值,为此,hash值冲突就会减少。
* 5.进一步减少hash值冲突,我可以在age后面乘以一个值--->原理:
* eg:
* name.hashCode() = 40,age = 20;
* name.hashCode() = 20,age = 40;
* 以上又会造成返回hash值冲突,当给age乘以一个数时,hash值冲突的概率会进一步减少。
* 6.利用编译器自动生成
*/
set.add(new Student(21, "zhang3"));
set.add(new Student(22, "li4"));
set.add(new Student(21, "xurong"));
set.add(new Student(23, "wang5"));
set.add(new Student(21, "zhang3"));
set.add(new Student(22, "li4"));
//3.将其输出
for (Iterator it = set.iterator();it.hasNext();) {
Student student = (Student)it.next();
System.out.println(student.getName()+"::"+student.getAge());
}
}
}
输出结果:
en.itcast.demain.Student@d6168cbb...en.itcast.demain.Student@d6168cbb
en.itcast.demain.Student@1a56f...en.itcast.demain.Student@1a56f
wang5::23
xurong::21
zhang3::21
li4::22