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日

时间: 2024-08-08 09:41:46

HashSet的初步了解的相关文章

【Java集合系列四】HashSet和LinkedHashSet解析

2017-07-29 16:58:13 一.简介 1.Set概念 Set可以理解为集合,非常类似数据概念中的集合,集合三大特征:1.确定性:2.互异性:3.无序性,因此Set实现类也有类似的特征. 2.HashSet HashSet继承自AbstractSet,实现了Set接口,但是其源码非常少,也非常简单.内部使用HashMap来存储数据,数据存储在HashMap的key中,value都是同一个默认值: 二.HashSet几个重要的方法 1.add(E e) HashSet的确定性,也可以理解

一次 HashSet 所引起的并发问题

背景上午刚到公司,准备开始一天的摸鱼之旅时突然收到了一封监控中心的邮件. 心中暗道不好,因为监控系统从来不会告诉我应用完美无 bug,其实系统挺猥琐. 打开邮件一看,果然告知我有一个应用的线程池队列达到阈值触发了报警. 由于这个应用出问题非常影响用户体验:于是立马让运维保留现场 dump 线程和内存同时重启应用,还好重启之后恢复正常.于是开始着手排查问题.分析首先了解下这个应用大概是做什么的. 简单来说就是从 MQ 中取出数据然后丢到后面的业务线程池中做具体的业务处理. 而报警的队列正好就是这个

Java连载92-Collections工具类、泛型初步

一.关于集合工具类 java.utils.Collections; Collections工具类可以对List集合中的元素进行排序,但是集合中的元素必须是“可以比较的”,实现Comparable接口. package com.bjpowernode.java_learning; import java.util.Collections; import java.util.*; ? public class D92_1_CollecitonsToolsClass { public static v

hashSet

import java.util.HashSet; import javax.print.attribute.HashAttributeSet; /* 集合 的体系: ------------| Collection 单例集合的根接口 ----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复. -------------------| ArrayList ArrayList 底层是维护了一个Object数组实现的. 特点: 查询速度快,增删慢.

java HashSet 与 TreeSet

Set接口并没有对Collection接口进行扩充,只是比Collection接口要求更加严格了,不能增加重复的元素,并且采用散列的储存方式,所以没有顺序 import java.util.Set; import java.util.HashSet; import java.util.TreeSet; public class Test { public static void main(String[] args) { //Set allSet = new HashSet();//@结果 1

HashSet的简单实现

HashSet的巧妙实现:就是建立一个“键值对”,“键”就是我们要存入的对象,“值”则是一个常量.这样可以确保, 我们所需要的存储的信息之是“键”.而“键”在Map中是不能重复的,这就保证了我们存入Set中的所有的元素都不重复.而判断是否添加元素成功,则是通 过判断我们向Map中存入的“键值对”是否已经存在,如果存在的话,那么返回值肯定是常量:PRESENT ,表示添加失败.如果不存在,返回值就为null 表示添加成功.

HashSet,TreeSet和LinkedHashSet的区别

Set接口Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个对象用equals方法比较返回true,Set就不 会接受这两个对象. HashSet: 顺序是不确定性的. LinkedHashSet:按照输入的顺序进行输出. TreeSet:SortedSet 接口的唯一实现类,保证集合元素处于排序状态. 1.HashSetHashSet有以下特点    不能保证元素的

初步了解CPU

了解CPU By JackKing_defier 首先说明一下,本文内容主要是简单说明CPU的大致原理,所需要的前提知识我会提出,但是由于篇幅我不会再详细讲解需要的其他基础知识.默认学过工科基础课. 一.总述 先从计算机的结构说起,在现代计算机中,CPU是核心,常常被比喻为人的大脑.现在的计算机都为“冯·诺依曼机”,“冯诺依曼机”的一个显著的特点就是由运算器.存储器.控制器.输入设备和输出设备组成.CPU是运算器和控制器合起来的统称,因为运算器和控制器在逻辑关系和电路结构上联系十分紧密,尤其在大

zerglurker的C语言教程004——指针初步讲解

在上次的教程里面,我提到了指针. 针对指针,这次我将简单的讲讲,后面我还会讲到--那个时候你应该有了相当的基础. 首先,先讲讲指针类型. 任何类型关键字后面加一个*符号,就会变成指针类型. 比如: char → char* 字符指针 int → int* 整数指针 double→double* 双精度指针 甚至还可以这样: char*→char** 字符指针的指针类型 →char*** 字符指针的指针的指针类型- 指针本质上是一个内存地址值,该内存地址上存放的是相关类型的数值.但是void*指针