1.现象
public class Test { public static void main(String[] args) { Set col = new HashSet(); Person p1 = new Person(11); Person p2 = new Person(12); Person p3 = new Person(13); Person p4 = new Person(11); col.add(p1); col.add(p2); col.add(p3); col.add(p4); //Person的HashCode()方法根据age判断,故添加不成功 p2.setAge(200); System.out.println(col.remove(p2));//此处移除失败 } }为什么在集合中移除元素失败?
2.HashCode的作用
如果需要查找一个集合中是否包含一个元素,如果集合的数量很大,势必导致查询的效率很低。使用Hash算法可以改善,将集合分成若干个存储区域,每个对象可以计算出一个哈希值,分组重查询对应存储区域,查询效率提高!
3.原因分析
col.remove(p2);//会自动进行equals比较,即p2重新计算的HashCode值如果在HashTable中存在(可能该值所对应的对象不同),则可以移除,否则移除不成功!
如果remove为false,即实际已经存在于类存中,但却移除失败,必将导致该部分内存溢出!
public class My { public static void main(String[] args) { Set col = new HashSet(); Person p1 = new Person(11); Person p2 = new Person(12); Person p3 = new Person(13); Person p4 = new Person(11); col.add(p1); col.add(p2); col.add(p3); col.add(p4); p2.setAge(200); System.out.println(col.remove(p2)); //导致哈希值不存在,equals方法返回false System.out.println("==============================="); p2.setAge(12); //重新修改为原来的 System.out.println(col.remove(p2)); //重新计算的哈希值存在,equals方法返回true } } class Person{ private int age; Person(int age){ this.age = age; } public int getAge(){ return age; } public void setAge(int age){ this.age = age; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; return true; } }
4.HashCode在集合中应用
boolean contains(Object o) 当且仅当此 collection 至少包含一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时,返回 true。
public class TT { public static void main(String[] args) { List<Student> list = new ArrayList<Student>(); Student s1 = new Student(20); Student s2 = new Student(18); Student s3 = new Student(22); Student s4 = new Student(20); list.add(s2); list.add(s3); list.add(s4); for(Object obj: list){ System.out.println(((Student)obj).getAge()+" HashCode:"+obj.hashCode()); } System.out.println(list.contains(s1));//true System.out.println(list.remove(s1));//true /* * s1对象并未添加至集合中去,但是此处输出true, * 即证明了一点,contains()会调用equals方法,由于s1与s4具有相同的HashCode,故输出为true */ } } class Student{ private int age; Student(int age) { this.age = age; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; return result; } 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; return true; } public int getAge() { return age; } }