HashSet的初步了解

HashSet是无序的、它在添加元素的时候、是无序的、输出的时候、而不是依据你所添加元素的顺序而打印出来。

import java.util.*;
public class HashSetDemo
{
    public static void main(String[] args)
    {
		HashSet hs = new HashSet();
        Add(hs);
		System.out.println(hs);
    } 
	public static void Add(HashSet hs)
	{
		for (int i = 1;i < 10; i++)
		{
			hs.add("java0" + i);
		}
	}
}

运行结果:

[java04, java05, java02, java03, java01, java08, java09, java06, java07]


这是特点之一,其二就是它在底层可以自动去除重复的元素、

import java.util.*;
public class HashSetDemo
{
    public static void main(String[] args)
    {
		HashSet hs = new HashSet();
        Add(hs);
		System.out.println(hs);
    } 
	public static void Add(HashSet hs)
	{
		hs.add("java01");
		hs.add("java02");
		hs.add("java01");
		hs.add("java03");
		hs.add("java01");
		hs.add("java03");
	}
}

运行结果:

[java02, java03, java01]

但是如果添加的是对象而不是单一元素呢?

我们来试试、

import java.util.*;
public class HashSetDemo
{
    public static void main(String[] args)
    {
		HashSet hs = new HashSet();
        Add(hs);
		show(hs);
    } 
	public static void Add(HashSet hs)
	{
		hs.add(new Person("lisi01", 22));
		hs.add(new Person("lisi02", 37));
		hs.add(new Person("lisi01", 22));
		hs.add(new Person("lisi03", 41));
	}
	public static void show(HashSet hs)
	{
		for (Iterator it = hs.iterator(); it.hasNext()  ; )
		{
			Person p = (Person)it.next();
			sop(p.getName() + "->" + p.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Person
{
	private String name;
	private int age;
	Person(String name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

运行结果:

lisi03->41
lisi01->22
lisi01->22
lisi02->37


我们可以发现、 里面有重复元素的存在、 HashSet它底层并没有为我们去除重复元素。为什么呢?

原因如下:

1:HashSet底层先调用了hashCode方法、当哈希值相同时再调用equals方法进行比较、但是系统不知道我们比较的标准、

所以我们要重写equals方法和hashCode方法。


import java.util.*;
public class HashSetDemo
{
    public static void main(String[] args)
    {
		HashSet hs = new HashSet();
        Add(hs);
		show(hs);
    } 
	public static void Add(HashSet hs)
	{
		hs.add(new Person("lisi01", 22));
		hs.add(new Person("lisi02", 37));
		hs.add(new Person("lisi01", 22));
		hs.add(new Person("lisi03", 41));
	}
	public static void show(HashSet hs)
	{
		for (Iterator it = hs.iterator(); it.hasNext()  ; )
		{
			Person p = (Person)it.next();
			sop(p.getName() + "->" + p.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Person
{
	private String name;
	private int age;
	Person(String name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public int hashCode()
	{
		return 1;
	}
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Person))
			return false;
		Person p = (Person)obj;	
		return this.name.equals(p.name) && this.age == p.age;
	}
}

运行结果:

lisi03->41
lisi02->37
lisi01->22


这样我们就可以进行去重了、先调用HashCode、复写方法、返回1,这样就调用equals方法来进行我们所需要的比较标准了。

其实为了提高效率、我们可以让它们有独立的哈希值、这样就可以避免进行无谓的比较了。


在这之前我们来测试一下、 是否真的是调用了hashCode和equals方法、我们可以把那段代码修改一下:


public int hashCode()
	{
		System.out.println(this.name + "....HashCode");
		return 1;
	}
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		System.out.println(this.name + "....equals...." + p.name);
		return this.name.equals(p.name) && this.age == p.age;
	}

运行结果:

lisi01....HashCode
lisi02....HashCode
lisi02....equals....lisi01
lisi01....HashCode
lisi01....equals....lisi02
lisi01....equals....lisi01
lisi03....HashCode
lisi03....equals....lisi02
lisi03....equals....lisi01
lisi03->41
lisi02->37
lisi01->22


从上面的结果得知、 是先计算哈希值、如果相同就调用equals、 反之则不调用。  那么我们可以依据这个来改进一下、

只需要把hashCode方法修改一下:

public int hashCode()
	{
		System.out.println(this.name + "....HashCode");
		return this.name.hashCode() + age*19;
	}

运行结果:

lisi01....HashCode
lisi02....HashCode
lisi01....HashCode
lisi01....equals....lisi01
lisi03....HashCode
lisi03->41
lisi02->37
lisi01->22


依据这个我们可以更加肯定、 当哈希值相同的时候,不再调用equals方法,当不同时,就调用equals、这样我们可以减少比较次数、从而提高效率。

记录一下。。2015年6月2日

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值