昨天去面试,考官问了一个关于Java的容器Hashset的问题,是说在加入自定义的对象时,如何设置对象的某一个属性为关键属性,即该属性相同则不能添加,该属性不同则可以添加。用Java编程还是太少,之前真的是没有遇到过类似问题,所以当时瞎扯一通,很遗憾也没有猜。回来看了看网上的讲解,自己又编了个程序试了试,终于明白了一点。唉,编程这东西,不积跬步无以至千里啊!

首先我编程发现,即使一模一样的两个对象,加入到Hashset中也是可以的。

import java.util.HashSet;

public class Car {
	private int price;
	private enumcolor color;
	
	public enum enumcolor{
		red,blue,black,white;
		private String value;
		
		public void setcolor(String c){
			this.setColor(c);
		}
		public String getColor() {
			return value;
		}
		public void setColor(String color) {
			this.value = color;
		}
	}
	
	public Car(int pri,enumcolor ecolor){
		this.price=pri;
		this.color=ecolor;
	}
	
	public enumcolor getColor() {
		return color;
	}
	
	public void setColor(enumcolor color) {
		this.color = color;
	}
	
	public int getPrice() {
		return price;
	}
	
	public void setPrice(int price) {
		this.price = price;
	}
	
	protected void showPrice(){
		System.out.println(this.price);
	}
	public static void main(String args[]){
			enumcolor cl1=enumcolor.black;
			enumcolor cl2=enumcolor.red;
			Car car = new Car(1,cl1);
			Car bus = new Car(1,cl1);
			HashSet<Car> carSet = new HashSet<Car>();
			carSet.add(car);
			carSet.add(bus);
			System.out.println(carSet);
			for(Car ite:carSet){
				System.out.println(ite);
			}			
		}	
}

如上面这段代码,建立了一个Car类,创建两个对象car和bus,这两个对象的价格都是1,颜色都是black,但是竟然可以都加入到Hashset中去!

为什么会这样呢?我上网搜了一下,Hashset在判断是否重复时,按如下机制进行工作当调用了 HashSet 的 add 方法存放对象 obj , HashSet 会首先调用 obj 的 hasCode 方法得到该对象的哈希码, HashSet 会使用一个算法把它的哈希码转换成一个数组下标,该下标“标记”了 obj 的位置。如果这个位置上的链表中没有元素,那么就把 obj 对象添加到链表上。如果这个位置上的链表中已经有了元素,则遍历这个链表,调用 obj 的 equals 方法,判断 obj 是否和其中的某个元素重复,如果没有重复的元素,那么就将 obj 添加到链表上;如果有重复的元素,则不会将 obj 对象存入 HashSet 中。另外自定义子类是继承了Object类的,其中判断重复的equals方法也是继承了父类的,所以我们要重写equals方法如下:

@Override 
    public boolean equals(Object st) 
    { 
        Car tempcar= (Car) st; 
        if (price==tempcar.price) return true; 
        else return false; 
    } 

这样就是以价格这一属性为关键属性进行比较对象是否重复了。

但是还没结束,上面已经说过了,如果hashCode返回值不同是不可能去调用equals方法去判断的,也就是还要重写hashCode,保证相同属性的对象hashCode也一样,所以重写hashCode如下:

public int hashCode() 
    { 
        return new Integer(price).hashCode(); 
    } 

同时覆盖了这两个函数后,我们的工作就完成了,为了显示清楚,再重写toString方法:

public String toString(){
    	return "color:"+color+",price:"+price;
    }

至此我们再进行试验就会发现,只要是价格相同的对象是无法同时添加进入hashset中去的了!



Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐