首页 > 代码库 > java基础巩固系列(五):ArrayList与HashSet的比较,以及HashCode分析

java基础巩固系列(五):ArrayList与HashSet的比较,以及HashCode分析

首先,我们需要知道的是ArrayList和HashSet类都在java.util包中,都是实现了Collection的类,Collection是一个标准。


然后,我们介绍下这两个类之间的区别:

1、ArrayList:相当于一个动态的数组,是一组有序的集合,当对象被添加到ArrayList时,对象会先找到第一个空缺的地方。这里有一点需要记得:放进去的是对象的引用,不是对象本身。然后,放入第二个对象,如果和第一个相同的话,依然按照顺序存放进去。也就是说,在这个有序集合里,每有一个对象就会放入一个引用,可能出现多个引用指向同一个对象的情况,但没有关系

package com.internet;
import java.util.ArrayList;

public class test {
	public static void main(String[] args){
		ArrayList c = new ArrayList();
		Integer a = new Integer(1);
		Integer b = new Integer(1);
		c.add(a);
		c.add(b);
		System.out.println(c.size()); //结果:2
		System.out.println(a.equals(b));//结果为true,可以看出两个对象是相等的
	}
}
2、HashSet:当放入对象时,首先查看里面是否有这样一个对象(这里判定的是对象的地址是否相同),如果有,则不放,如果没有才会放入:

MyTest.java

package com.internet;
class MyTest
{
	int x;
	int y;
    public  MyTest(int x,int y)
    {
    	this.x=x ;
    	this.y=y ;
    }
}
ReflectTest.java

package com.internet;

import java.util.HashSet;

public class ReflectTest {
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		
		MyTest t1 = new MyTest(1, 1);
		MyTest t2 = new MyTest(2, 2);
		MyTest t3 = new MyTest(1, 1);
		
		hs.add(t1);
		hs.add(t2);
		hs.add(t3);
		hs.add(t1);
		
		System.out.println(hs.size()); //结果:3
	}

}
在这里,需要注意一点:在FlectTest.java中,声明了t3对象,这里的t3与t1的构造的x,y值相同,但是t1和t3都存入了hs中,

就是因为,这里说的是否有相同的对象指的是内存地址,不是数值。


其次,紧接上边的HashSet的例子,如果我们需要让t1和t3是相同,在t1存进去之后t2不能够存进去,应怎么办呢?
我们需要在MyTest.java中覆盖equals()方法:

package com.internet;
import java.util.*;

class MyTest1
{
	int x;
	int y;
    public  MyTest1(int x,int y)
    {
	     this.x=x ;
	     this.y=y ;
    }
    
	@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;
		MyTest1 other = (MyTest1) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
}
然后,在FlectTest.java中得到的结果就是2了。

具体该怎么覆盖呢?在MyTest.java代码窗口点击右键------>找到“Source"并点击------->找到”Generate hashCode() and equals()"并点击。


还有,在对象中覆盖了equals()方法之后,当一个对象存储进了HashSet集合之中后,就不能够修改这个对象中参与计算哈希值的字段了。否则,对象修改后的哈希值与最初存进HashSet集合中的哈希值就不同了。这时,如果要删除某个存进去的对象,就不能够通过哈希值正确删除了,从而造成内存泄露。

package com.internet;

import java.util.*;
public class ReflectTest4
{
   public static void main(String[]args)
   { 
    //面向父类的编程或者面向接口编程 
	   Collection c1=new HashSet() ; 
       MyTest1 t1=new MyTest1(2,2)  ;
       MyTest1 t2=new MyTest1(3,4)  ;
       MyTest1 t3=new MyTest1(2,2)  ;
       c1.add(t1) ;
       c1.add(t2) ;
       c1.add(t3) ;
       c1.add(t1) ;
       
       System.out.println(c1.size());  //结果:2
       
       
       t1.x =4;
       c1.remove(t1);
       
       System.out.println(c1.size());  //结果:2 
   }
   
}
由上边我们可以看到,t1对象没有被正确删除。因为程序修改了t1中能够生成hashcode的值x,导致生成的hashcode与存进去的不一致,不能删除。


java基础巩固系列(五):ArrayList与HashSet的比较,以及HashCode分析