出了集合框架的话equals 就未必是靠哈希值来判断的了,哈希值是地址值和你存储的元素的内容通过某种算法组合出来的一种值,很有可能储存在A内存的数值X 和储存在B内存的数值y 是同一个哈希值,比如你比较一个字符串用equals 比较肯定不一样的X 和 Y 但是也许哈希值一样。
equals 比较的字符串是比较他们的真实值 而不是哈希值。
在哈希集合框架内equals 就靠的是比较哈希值来判断是否是一个元素了。所以为了让你的哈希表也许在同一个哈希值下有两个不同的元素。
需求:去除hashset 中的具有相同值的Person类
- package SetShow;
- import java.util.HashSet;
- import java.util.Iterator;
- public class HashSetDemo {
-
- public static void main(String[] args) {
-
- HashSet hs = new HashSet();
- hs.add(new Person("a1",11));
-
- hs.add(new Person("a2",12));
- hs.add(new Person("a2",12));
-
- hs.add(new Person("a3",13));
-
- Iterator it = hs.iterator();
- while(it.hasNext())
- {
- Person p = (Person) it.next();
- sop(p.getName()+" : "+p.getAge());
- }
- }
- public static void sop(Object obj)
- {
- System.out.print(obj);
- System.out.println();
- }
- }
- class Person
- {
- private String name;
- private int age;
- Person(String name, int age)
- {
- this.name = name;
- this.age = age;
- }
- public int hashCode()//按照条件而设定哈希值
- {
- System.out.println(this.name+" hash code "+name.hashCode()+age);
- return name.hashCode()+age*27;
- }
- public String getName()
- {
- return name;
- }
- public int getAge()
- {
- return age;
- }
-
- public boolean equals(Object obj)
- {
- if(!(obj instanceof Person))// obj instanceof person:在这里说,obj 是 Person吗
- return false;
- Person p = (Person) obj;
- System.out.println(this.name+"...equals ?..."+p.name);
- return this.name.equals(p.name)&& this.age == p.age;
- }//this equals 在运行contains 的时候被自动调用了,所以如果想比较其他的元素的内容可以自己编写一遍
- }
复制代码
输出结果:
a1 hash code 305611
a2 hash code 305712
a2 hash code 305712
a2...equals ?...a2
a3 hash code 305813
a1 : 11
a2 : 12
a3 : 13
从上边的例子可以看出,equals 方法在使用前是调用的hashcode()方法的,名字和年龄经过哈希算法过后就变成了不同的数值,当第二个a2进入哈希表的时候发现他的哈希值名字和以前的那个a2 一样,所以就调了equals 方法进行比较,比较两个person 的name 和 age,具体的操作是:(第二个a2) .equals(第一个a2)。如果发现哈希值一样,内容也一样就判定指向的是同一个对象,则不会把同一个对象存入哈希表两次。所以后来就自动出现了只存入a1,a2,a3的三个情况。
和list 一样hashset 的remove 和 conatins 方法也是依赖equals方法,equals 依靠的是hashcode。 |