A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 汪小照 中级黑马   /  2012-9-26 12:22  /  2136 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

package cn.heima;
import java.util.*;
public class HashCodeTest {
public static void main(String[] args)
{
  Set<Student> set = new HashSet<Student>();
  Student s1 = new Student("lisi",12);
  Student s2 = new Student("zhangsan",13);
  Student s3 = new Student("lisi",12);
  set.add(s1);
  set.add(s2);
  set.add(s3);
  s1.age = 10;
  set.remove(s1);     //不加这句时打印的集合大小是2,加了这句打印的集合大小还是2,为什么删不掉呢?
  System.out.println(set.size());
}
}
class Student{
int age;
String name;
Student(String name,int age)
{
  this.age = age;
  this.name = name;
}

public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + age;
  result = prime * result + ((name == null) ? 0 : name.hashCode());
  return result;
}
public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  final Student other = (Student) obj;
  if (age != other.age)
   return false;
  if (name == null) {
   if (other.name != null)
    return false;
  } else if (!name.equals(other.name))
   return false;
  return true;
}
}

6 个回复

倒序浏览
因为set里面存入的还是age属性没有改变前的s1,你可以打印一下set.remove(s1); 其实返回的是false,说明没有将s1移除;或者打印一下set.contains(s1);返回的也是false。remove()会调用equals()方法,这时改变前的s1和改变后的s1不是一个对象。
总之,set.remove(s1); 没有将集合中的s1移除,所以打印集合始终是2.
回复 使用道具 举报
我知道是没有被移除,但我想知道为什么有关参与计算hashCode值的字段改变后就移不掉了,我想知道更清楚原理的东西,打印它是false,这只是一个结果,但我想知道为什么是这样的结果,具体分析是怎么来的?
回复 使用道具 举报
本帖最后由 杜佳瑞 于 2012-9-26 14:39 编辑
汪小照 发表于 2012-9-26 13:58
我知道是没有被移除,但我想知道为什么有关参与计算hashCode值的字段改变后就移不掉了,我想知道更清楚原理 ...


HashSet中加入元素以及删除元素,依赖的方法是hashcode和equals方法。
而你又复写了hashcode方法和equals方法,哈希值是通过name和age算出来的,所以更改age的值后,再调用remove方法会自动调用hashcode方法判断有没有这个对象,所以和更改之前的哈希值肯定不一样。。。既然找不到更改之后的对象肯定就移除不成功了
明白了吗?
回复 使用道具 举报
{:soso_e179:}楼上正解!!哥们说的很清楚,很明白,给力。
回复 使用道具 举报
  1. set.add(s1);
  2. set.add(s2);
  3. set.add(s3);
  4. //假如s1存储前Hash值计算在第一区域也就是说s1存储在第一区域
  5. s1.age = 10;  //假如s1重新存储后Hash值计算在第二区域
  6. set.remove(s1); //去第二区域能找到s1吗?找不到!因为s1在第一区域,第二区域没有s1
  7. //HashSet为了提高存储效率,把一整块区域分别分成了数份小的区域,并且用Hash值区分每一小区域
复制代码
回复 使用道具 举报
黄敏 中级黑马 2012-9-26 20:54:30
7#
LZ,请转移高新技术看张老师的视频中说的很清楚,仔细点
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马