哈希表-存储自定义对象

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
上一篇:第一次考试出错题equals和hashcode


下一篇:漫画:什么是字符串匹配算法?