标签:
----------------------------Java培训、Android培训、期待与您交流! -------------------------------
ArrayList_HashSet的比较及Hashcode分析
看以下三段代码:
1、定义一个点类(Point)
1 package com.itheima.day1; 2 3 public class ReflectPoint { 4 private int x; 5 public int y; 6 7 public ReflectPoint(int x, int y){ 8 super(); 9 this.x = x; 10 this.y = y; 11 } 12 }
2、将几个点存入ArrayList集合中的代码:
1 public class ReflectTest6 { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 Collection co = new ArrayList(); 6 7 ReflectPoint point1 = new ReflectPoint(3, 4); 8 ReflectPoint point2 = new ReflectPoint(5,8); 9 ReflectPoint point3 = new ReflectPoint(3, 4); 10 11 co.add(point3); 12 co.add(point2); 13 co.add(point1); 14 co.add(point3); 15 16 System.out.println(co.size());//结果:4 17 18 } 19 20 }
3、将同样的点存入HashSet集合中的代码:
package com.itheima.day1; import java.util.*; public class ReflectTest7 { public static void main(String[] args) { // TODO Auto-generated method stub Collection co = new HashSet(); ReflectPoint point1 = new ReflectPoint(128, 128); ReflectPoint point2 = new ReflectPoint(5,8); ReflectPoint point3 = new ReflectPoint(128, 128); co.add(point3); co.add(point2); co.add(point1); co.add(point3); System.out.println(co.size());//结果:3 }
分析:
1、我们都知道,HashSet集合中元素不能重复。
2、从第三段代码结果3可以看出,HashSet集合将point1和point3视为两个不同的点。原因是因为point1和point3的hashCode不一样。
HashSet增加元素时判断是否有相同元素的方法:
1)先判断要增加的元素的hashCode和集合中元素的hashCode是否相同,如果不相同,则直接将此元素加入集合中;
2)如果hashCode相同,则在根据元素的equals方法进行判断是否有重复元素。
3、而我们一般认为如果两个点的坐标相同,我们就视为它们是同一个点。
这就要我们重写点类的hashCode()和equals()方法。
代码示例:
package com.itheima.day1; public class ReflectPoint { private int x; public int y; //public String str1 = "ball"; //public String str2 = "basketball"; //public String str3 = "java"; public ReflectPoint(int x, int y){ super(); this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public String toString(){ return str1+":"+str2+":"+str3; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReflectPoint other = (ReflectPoint) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } }
注意:
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
代码示例:
package com.itheima.day1; import java.util.*; public class ReflectTest7 { public static void main(String[] args) { // TODO Auto-generated method stub Collection co = new HashSet(); ReflectPoint point1 = new ReflectPoint(128, 128); ReflectPoint point2 = new ReflectPoint(5,8); ReflectPoint point3 = new ReflectPoint(128, 128); co.add(point3); co.add(point2); co.add(point1); co.add(point3); point3.setY(0); co.remove(point3); System.out.println(co.size());//结果仍然为2 } }
说明,此point3的hashCode已经被改变,所以在集合中已经检索不到这个对象,导致删除失败,这个对象就会一直存在,造成内存泄漏。
标签:
原文地址:http://www.cnblogs.com/alvis2015/p/4301635.html