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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

在每个覆盖equals方法的类中,也必须覆盖hashcode方法,如果不这么做,就会违反Object.hashCode 的通用约定,从而导致该类无法结合散列的集合一起正常运作,这样的集合包括HashMap,HashSet和Hashtable.
jdk6中Object规范:
  1、在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有修改,那么对着同一个对象调用多次,hashcode方法都必须始终如一的返回同一个整数。在同一个应用程序的多次执行过程中,每次执行返回的整数可以不一致。
  2、如果两个对象根据equals(Object)方法比较是相等的,那么调用着两个对象中任意一个对象的hashcode方法都必须产生同样的整数结果。
  3、如果两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashcode方法,则不一定要产生不同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
因为没有覆盖hashCode方法违反了第二条,相等的对象必须具有相等的散列码(hash code)。
public class Student {    private String name ;        private int age;        private String sex;        private long score;        private List food;        private Map<String ,String> clothes;        private String[] others;        private kid kid;        public kid getKid() {        return kid;    }    public void setKid(kid kid) {        this.kid = kid;    }    public String[] getOthers() {        return others;    }    public void setOthers(String[] others) {        this.others = others;    }    public Map<String, String> getClothes() {        return clothes;    }    public void setClothes(Map<String, String> clothes) {        this.clothes = clothes;    }    public List getFood() {        return food;    }    public void setFood(List food) {        this.food = food;    }        public long getScore() {        return score;    }    public void setScore(long score) {        this.score = score;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }        public Student(String name, int age, String sex) {        this.name = name;        this.age = age;        this.sex = sex;    }  
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (clothes == null) {
if (other.clothes != null)
return false;
} else if (!clothes.equals(other.clothes))
return false;
if (food == null) {
if (other.food != null)
return false;
} else if (!food.equals(other.food))
return false;
if (kid == null) {
if (other.kid != null)
return false;
} else if (!kid.equals(other.kid))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (!Arrays.equals(others, other.others))
return false;
if (score != other.score)
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
}

只覆盖了equals方法没有覆盖hashCode方法,测试代码:
public class Demo {    public static void main(String[] args) {                Map<Student ,String> map  = new HashMap();         map.put(new Student("一号" ,18 , "男") , "测试一号");                String string = map.get(new Student("一号" ,18 , "男"));                System.out.println(string);            }}
结果:
由于没有覆盖hashCode方法,从而导致两个相等的实例具有不相等的代码,违反了hashCode约定,其中的put方法将对象放在一个散列桶中(hash bucket)中,get方法却在另一个散列桶中查询这个对象,即使这两个实例正好被放在同一个散列桶,get方法也必定会找到这个对象。此时添加一个hashCode方法:
结果:
添加了合法的hashCode方法,就确保了相等的对象总是具有同样的散列码。但是由于固定了返回值,使得每个对象都具有相同的散列码,导致每个对象都被映射到同一个散列桶中,是散列表退化为链表(linked list)。使得本该线性时间运行的程序变成了平方级时间在运行,对于大规模的散列表而言,这会关系扫散列表是否正常工作。
散列码的理想计算方式:
各种数据类型的散列码的计算方式,详情参考每种数据类型中源码中的hashCode方法。


11 个回复

倒序浏览
66666
回复 使用道具 举报
6666
回复 使用道具 举报
回复 使用道具 举报
666666666666
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马