本帖最后由 student 于 2013-5-25 15:28 编辑
我先解答第2个问题,再解答第1个问题。
我们知道,Set集合中不能存放相同元素,为了保证元素唯一性,就发明了HashCode(哈希值)。这种方式
将集合分成若干个存储区域,每一个对象可以计算出一个哈希值,可以将哈希值分组,每组分别对应某个存
储区域,根据一个对象的哈希值就可以确定该对象存储在哪个区域,如下图所示。
HashSet就是采用哈希算法,实现元素存储的集合,它内部使用对某个数值n进行取余的方式对哈希码进行
分组和划分对象存储区域。Object类中定义了一个hashCode()方法来返回每个Java对象的哈希值,当从HashSet
集合中查找某个对象时,Java系统首先调用对象的hashCode方法获取对象的哈希码,根据该哈希码找到相应的
存储区域,然后取出该存储区域的每个元素与该对象进行equals方法比较,这样不用遍历集合中的所有元素就可
以快速进行比较。
所以,我觉得hashCode代表某一块内存地址,但是不一定代表某一块内存地址,因为我们可以覆盖hashCode方法,
自定义自己的哈希值,如下面的例子,在Person类中覆盖了hashCode方法:- import java.util.HashSet;
- import java.util.Iterator;
- class Person {
- private String name;
- private int age;
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
- public int hashCode() {
- // 自定义的哈希值为:姓名的哈希值加上年龄
- return name.hashCode() + age;
- }
- // 复写Object类的方法
- public boolean equals(Object obj) {
- // 如果传入的参数不是Person对象
- if (!(obj instanceof Person))
- return false;
- Person p = (Person) obj;
- //名字相同,并且年龄相同则认为是相同元素
- return (this.name.equals(p.name)) && (this.age == p.age);
- }
- }
- public class HashSetDemo {
- public static void main(String[] args) {
- HashSet<Object> hs = new HashSet<Object>();
- hs.add(new Person("a1", 11));
- hs.add(new Person("a2", 12));
- hs.add(new Person("a2", 12));
- hs.add(new Person("a4", 14));
- //遍历输出集合元素
- Iterator<Object> it = hs.iterator();
- while (it.hasNext()) {
- Person p = (Person) it.next();
- System.out.println(p.getName() + " " + p.getAge());
- }
- }
- }
复制代码向Set集合中添加元素时,首先调用hashCode方法获取元素的哈希值,当该元素哈希值和集合中某个元素的哈希值相同时,
才调用equals方法。
return (this == obj)中,this表示当前对象,也就是新添加到Set集合中的对象就是this,而其他的已经添加到集合中的对象就是obj。当前对象和
集合中的对象进行比较,确定该对象是否已经存在,如果存在则阻止新对象插入到集合中,添加失败,这就保证的元素的唯一性。 |