Java学习笔记之集合(五):HashSet集合的实现原理

package com.collection.set;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

/*
集合的体系:
----| Collection: 单例集合的根接口
-------| List:实现了List接口的集合类,具备的特点:有序,可重复;
----------| ArrayList:底层是维护了一个Object数组实现的;特点:查询速度快,增删慢;
----------| LinkedList:底层是使用了链表数据结构实现的;特点:查询速度慢,增删快;
----------| Vector(了解即可):底层也是维护了一个Object数组实现的,与ArrayList是一样的;但是Vector是
				线程安全的,操作效率低,所以被ArrayList取代了;ArrayList不是线程同步的,操作效率高;
				
-------| Set:实现了Set接口的集合类,具备的特点:无序,不可重复;
----------| HashSet:底层是使用了哈希表来支持的;特点:存取速度快;

	HashSet的实现原理:
		往HashSet中添加元素的时候,HashSet会先调用元素的hashCode()方法得到元素的哈希值,然后通过元素的
		哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置;
		元素的哈希值相当于元素在内存中的存储地址;
		
		算出位置之后分两种情况存储:
		情况一:
			如果算出元素存储的位置目前没有其他任何元素存在,那么该元素可以直接存储到该位置上;
		情况二:
			如果算出该元素存储的位置目前已经存在别的元素了,那么HashSet会调用元素的equels方法与该位置
			的元素再比较一次;如果equals返回的是true,那么该元素与这个位置上的元素就视为同一个元素,
			不允许添加;如果equals返回的是false,那么该元素允许添加;
			问题:哈希表中同一个位置可以添加多个元素吗?
			可以。哈希表的其中一个特点:桶式结构。也就是说哈希表中的每个位置都相当于一个桶,可以存储多个元素;
		
		

----------| TreeSet:

	无序:指添加元素和顺序和取出元素的顺序是不一致的;
				
*/

class Person{
	int id;
	String name;
	
	public Person(int id, String name) {
		this.id = id;
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "{id=" + id + ",name=" + name + "}";
	}
	
	@Override
	public int hashCode() {
	
		// 向HashSet中每添加一个元素就会调用一次元素的hashCode()方法;
		System.out.println("===== 调用了hashCode()方法 =====");
		
		// 重写hashCode()方法,使元素的id一样时,在哈希表中存储的是同一个位置;
		return this.id;
	}
	
	@Override
	public boolean equals(Object obj) {
		// 重写equals,使id一样时,是同一个元素对象;
		Person p = (Person)obj;
		return this.id == p.id;
	}
	
}

public class Demo5 {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Test
	public void test1(){
		Set set = new HashSet();
		set.add("张三");
		set.add("李四");
		set.add("王五");
		
		// 无序,不可以重复;
		System.out.println("添加成功了吗?" + set.add("李四")); // 元素不可重复;添加失败,返回false;		
		System.out.println("集合中的元素:" + set); // 输出元素的顺序和添加元素的顺序是不一致的
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Test
	public void test2(){
		Set set = new HashSet();
		set.add(new Person(1, "张三"));
		set.add(new Person(2, "李四"));
		set.add(new Person(3, "王五"));
		
		/*
		问题:此处元素能添加成功吗?
		能。因为根据上面所说的HashSet的实现原理,此处新创建的Person对象的哈希值是唯一的,所以可以添加;
		当重写hashCode()方法和equals()方法后,就不能添加成功了。
		 */
		System.out.println("添加成功了吗?" + set.add(new Person(2, "冯二")));
		
		System.out.println("集合中的元素:" + set);
	}
}


















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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值