Java---27---Set集合及其子类HashSet

Set中元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。

Set中的方法和Collection中的方法是一样的。

常见子类:HashSet  TreeSet

HashSet 底层数据结构是哈希表

TreeSet 底层数据结构是二叉树

import java.util.HashSet;
import java.util.Iterator;
class Person{
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//set and get methods
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

}
public class SetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//method1();
		method2();
	}

	public static void method1() {
		HashSet hs = new HashSet();

		hs.add("01");
		hs.add("02");
		hs.add("03");
		hs.add("04");
		// 无序性
		sop(hs);

		hs.add("02");
		// 唯一性
		sop(hs);
		sop("是否添加进去:" + hs.add("02"));
	}
	/**
	 * 存入自定义对象,如果姓名和年龄相同视为同一个人,重复元素
	 */
	public static void method2 (){
		HashSet hs = new HashSet();

		hs.add(new Person("01",10));
		hs.add(new Person("02",11));
		hs.add(new Person("03",12));
		hs.add(new Person("04",13));
		/*打印
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		*/
		//添加一个相同元素
		hs.add(new Person("01", 10));
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		//没解决啊。。。两个01::10

	}
	public static void sop(Object object) {
		System.out.println(object);
	}

}

我们要求 姓名和年龄相同视为是重复元素,按照Set的特性来说是不应该被保存的,结果却是存上了。。。

解决:覆盖元素的hashCode 方法,建立自己的哈希值,同时覆盖equals方法。

覆盖元素HashCode方法 是因为,在Set中存入元素,首先被判断的就是元素的哈希值,只有当元素的哈希值没有出现过的时候,才会将元素存入。

覆盖equals方法是因为,两个元素的哈希值相同,但是这两个元素不一定是相同的,因此来判断一下,并根据返回值来决定该元素最终能否被存入。

package ssssssss;
import java.util.HashSet;
import java.util.Iterator;
class Person {
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if (!(obj instanceof Person))
			return false;
		Person person = (Person) obj;
		//打印      表示此方法被调用
		System.out.println(this.name + "******equals*****" + person.name);

		return this.name.equals(person.name) && this.age == person.age;
	}
	//覆盖hashCode方法  建立Person自己的哈希值
	public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println(this.name + "..........hashCode");
		return 13;
		//按照条件设定哈希值
		//return name.hashCode() + age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

}
public class SetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		method2();
	}
	/**
	 * 存入自定义对象,如果姓名和年龄相同视为同一个人,重复元素
	 */
	public static void method2 (){
		HashSet hs = new HashSet();

		hs.add(new Person("01",10));
		hs.add(new Person("02",11));
		hs.add(new Person("03",12));
		hs.add(new Person("04",13));
		/*打印
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		*/
		//添加一个相同元素
		hs.add(new Person("01", 10));
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		//没解决啊。。。两个01::10
		//覆盖 hashcode方法,建立自己的哈希值

	}
	public static void sop(Object object) {
		System.out.println(object);
	}

}

打印结果:

01..........hashCode
02..........hashCode
02******equals*****01
03..........hashCode
03******equals*****01
03******equals*****02
04..........hashCode
04******equals*****01
04******equals*****02
04******equals*****03
01..........hashCode
01******equals*****01
01::10
02::11
03::12
04::13

返回一个相同的哈希值,通过打印结果我们不难猜出此程序的运行过程:

01先生成一个哈希值,因为此时就只有01一个元素,所以存入

02再生成一个相同的哈希值,然后跟01比较,不是同一元素,存入

03再生成相同的哈希值,然后跟01和02进行比较,确定没有相同元素,存入

04也是一样,跟01 02 03比较完后,存入

接着就是重复元素01了,比较发现跟第一次存入的01是相同的,

返回false,没有存入。

结论:

HashSet是如何保证元素唯一性的呢?

通过元素的两个方法:hashCode和equals

只有当元素的哈希值相等的时候才会判断equals方法

那如果生成不同的哈希值的话,就可以大大的减少程序的运行次数。

package ssssssss;
import java.util.HashSet;
import java.util.Iterator;
class Person {
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if (!(obj instanceof Person))
			return false;
		Person person = (Person) obj;
		//打印      表示此方法被调用
		System.out.println(this.name + "******equals*****" + person.name);

		return this.name.equals(person.name) && this.age == person.age;
	}
	//覆盖hashCode方法  建立Person自己的哈希值
	public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println(this.name + "..........hashCode");
		//return 13;
		//按照条件设定哈希值
		return name.hashCode() + age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

}
public class SetDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		method2();
	}
	/**
	 * 存入自定义对象,如果姓名和年龄相同视为同一个人,重复元素
	 */
	public static void method2 (){
		HashSet hs = new HashSet();

		hs.add(new Person("01",10));
		hs.add(new Person("02",11));
		hs.add(new Person("03",12));
		hs.add(new Person("04",13));
		/*打印
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		*/
		//添加一个相同元素
		hs.add(new Person("01", 10));
		Iterator it = hs.iterator();
		while (it.hasNext()){
			Person person = (Person)it.next();
			sop(person.getName()+"::"+person.getAge());
		}
		//没解决啊。。。两个01::10
		//覆盖 hashcode方法,建立自己的哈希值

	}
	public static void sop(Object object) {
		System.out.println(object);
	}

}
时间: 2024-08-06 02:51:38

Java---27---Set集合及其子类HashSet的相关文章

Java 集合系列 16 HashSet

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 Java 集合系列 05 Vector详细介绍(源码解析)和使用示例 Java 集合系列 06 Stack详细介绍(源码解析)和使用示例 Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和

Java学习(set接口、HashSet集合)

一.set接口 概念:set接口继承自Collection接口,与List接口不同的是,set接口所储存的元素是不重复的. 二.HashSet集合 概念:是set接口的实现类,由哈希表支持(实际上是一个HashMap集合).HashSet集合元素的提取顺序与存储顺序不相同. 采用哈希表数据结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法. 2.1哈希表 什么是哈希表? 链表与数组的组合. 哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时

JAVA学习第三十九课(常用对象API)- 集合框架(七)— Map集合及其子类对象

一.Map集合常见子类 HashTable:内部结构是哈希表,同步,此实现提供所有可选的映射操作,不允许使用 null 值和 null 键 (HashTable下有子类Properties,使用频率非常高,用来存储键值对型的配置文件信息和IO技术相结合) HashMap:内部结构是哈希表,不同步,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键. TreeMap:内部结构是二叉树,不同步,可以对Map集合中的键进行排序. 二.HashMap演示 import java.ut

黑马程序员——java——Map集合的子类HashMap的简单操作方法

Map集合的子类HashMap的简单操作方法 import java.util.HashMap; import java.util.Iterator; public class HashMapDemos { public static void%r0main(String[] args) { // HashMap<Studenti,String> hm = new HashMap<Studenti,String>(); hm.put(new Studenti("kk&qu

【转】Java如何克隆集合——深度拷贝ArrayList和HashSet

原文网址:http://blog.csdn.net/cool_sti/article/details/21658521 原英文链接:http://javarevisited.blogspot.hk/2014/03/how-to-clone-collection-in-java-deep-copy-vs-shallow.html 程序员通常会误用集合类(如List.Set.ArrayList.HashSet)所提供的拷贝构造函数或其它方法来完成集合的拷贝.值得记住的一点是,Java中集合提供的拷贝

java:Set对象TreeSet有序子类,HashSet无序子类,重复对象二

TreeSet有序子类; HashSet无序子类 重复重复元素,Object对象是通过equals和hashCode来进行过滤的. 如果将上一篇提到中的例子中的TreeSet,换成HashSet,那么代码就不会过滤从的对象 HashSet无序子类,如何过滤重复的对象呢?(单个元素是可以过滤,但相同的对象不会) Person: public class Person implements Comparable<Person> { private String name; private int

Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 上一篇总结了下ArrayList .LinkedList和Vector比较,今天泥瓦匠总结下Hash .LinkedList和Vector比较.其实大家都是Collection,只不过有点各自特性.那就是数据结构的不同表现. 一.Set回顾 一个不包括重复元素(包括可变对象)的Collection,是一种无序的集合.Set不包含满 a.equals(b) 的元素对a和b,并且最多有一个null.泥瓦

java基础之集合篇

(一) 集合类位于JDK中java.util包中. 常用的集合类型分布在java.util.Collection和java.util.Map接口中. java.util.Collection=>List; java.util.Collection=>Set; java.util.Map; 注意:在java的继承中,子类可以继承父类:同样子接口也可以继承父接口,目的是扩充子接口的功能. List: 1.基本概念 首先,list是变长的 2.其次,list中可以存储多种数据类型,但仅限于引用类型:

java学习总结-集合(collection)

本人正在学习java基础知识,非常感恩能够看到毕向东老师的java视频,他引领了我去思考问题,而不是生硬的去记一些知识点,下面是我对集合学习的总结和思考. 01-常用对象API(集合框架-概述).avi 问题1:什么是集合框架? 首先要理解集合这个词,它有另一个更加形象的名词:容器,所谓容器就是装载事物的器皿,而在java中最大的特征就是面向对象,所以可以推断出其实它就是用来装载对象的,便于我们去遍历和处理这些对象,关于框架的含义,其实就是它不是一个单独对象,而是有很多对象,并且相互存在区别和关