ArrayList、HashSet的比较及Hashcode分析

来源:互联网 发布:河南网络主播招聘 编辑:程序博客网 时间:2024/05/17 03:08

------- android培训、java培训、期待与您交流! ----------

java中有内存泄露吗?为什么?

有,所谓的内存泄露就是这个对象不用了,结果这个对象一直占用内存空间没有被释放,这就叫内存泄露。有个对象一直不用了,一直往下运行,占用空间。当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下的时候,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。

hashCode方法的作用?

加入一个集合中存入了一万个元素,现在想要向集合中放进去一个元素,如果有相同的就放不进去,如果没有就可以放进去,取出第一个比较是否相等,取出第二个,第三个,依次比较直到取出第一万个进行比较。显然,这样必须得找一万遍才可以。所以为了提高效率,产生了hashCode这种算法,它把集合分成了若干个区域,每一个要存进来的对象可以算出来一个值,根据算出来的值,就把其放入相应的区域,假设将集合分成32个区域,此时要放入一个对象,算出对象的值(哈希值)为区域1中,现在要查找某个对象,这时可以先算出这个对象的hashCode值,看他属于第几个区域,如果属于第二个区域,就在第二个区域中判断是否有相等的对象,这样查找的性能提高了。这就是hashCode的作用。要想让hashCode有作用的话,前提必须是对象存到HashSet集合中。

代码演示:

public class ReflectTest2 {public static void main(String[] args) {//ArrayList可以放置重复的对象的应用。//HashSet放入之前判断有没有重复的,如果有就不放进入;并不是覆盖//面向接口编程或者面向父类编程//Collection collections = new ArrayList();这种Collection collections = new HashSet();//面向接口编程或者面向父类编程ReflectPoint pt1 = new ReflectPoint(3, 3);ReflectPoint pt2 = new ReflectPoint(5, 5);ReflectPoint pt3 = new ReflectPoint(3, 3);collections.add(pt1);collections.add(pt2);collections.add(pt3);collections.add(pt1);/*如果希望以上的p1和p3相等,那么就必须自己写equals和hashCode方法,否则,默认的equals方法比较的是hashCode的值,通常hashCode的值是根据内存地址换算出来的。所以就在ReflectPoint中产生这两个方法,覆盖后hashCode值就是根据x和y了,而不是根据内存引用地址产生的。、所以输出的长度就为2。*///存进去后改y的值,这种情况下会发生内存泄漏。pt1.y = 7;collections.remove(pt1);//输出2,删除不掉的System.out.println(collections.size());}}

public class ReflectPoint {private int x;public int y;public String str1 = "ball";public String str2 = "basketball";public String str3 = "itcast";public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}//如果将这个方法干掉,显示的结果有可能是3(也有可能是2)@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;result = prime * result + y;return result;}@Overridepublic 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;}@Overridepublic String toString(){return str1 + ":" + str2+":"+str3;}}

以上代码分析:

不覆写hashCode()和equals方法时候,new ArrayList的时候输出的长度为4?

new HashSet时候输出长度为3。由此引发的一个问题:ArrayList和HashSet存储的区别?对于ArrayList它是一种有顺序的集合,就相当于一个数组,当放入一个对象的时候,首先找到第一个空位置,将对象的应用放进去。依次进行,放入对象的应用,如果遇到相同的引用时,还会依次放进去。其中有多个引用变量指向的是同一个变量,也没有关系。按照先后顺序依次放入。

 

没有实现equals、hashCode方法为什么就等于3呢?

因为这两个对象的hashCode的值是按照内存地址算出来的。这两个本来认为该相同的对象,分别被存放到了不同的区域,当要找这个对象的时候,我在我的区域中找,不在那个区域找。那个区域也有一个相同的。但是不去那个区域找就被放进去了。为了让这个相等的对象也放在相等的区域,如果两个对象equals相等的话,应该让它们的hashCode也相等。如果对象不存放到hashSet集合中,就不用hashCode了。

注意:hashSet放入之前先比较有没有相等的对象,如果有就不会放进去,注意,不是覆盖,而是不放进去,如果想覆盖原来的对象,必须将原有的remove掉。


0 0