ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java集合(三)—— Set详解

2021-10-02 18:02:08  阅读:197  来源: 互联网

标签:Set Java HashMap HashSet 对象 学号 hashCode 详解 Student


Set接口

一、HashSet

public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, Serializable

HashSet继承自Set接口,无序、不可重复的,线程不安全,存取速度快。
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置。
如果两个元素的equals()方法返回true,但它们的hashCode()返回值不相等,hashSet将会把它们存储在不同的位置,但依然可以添加成功,

1、实现原理

HashSet 是基于 HashMap 实现的,HashSet的值存放于 HashMap的key上,HashMap的value统一为present,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层HashMap 的相关方法来完成,HashSet 不允许重复的值。

2、扩容机制

HashMap 默认初始容量为16(为何是16?),加载因子为 0.75(即当 元素个数 超过 容量长度的0.75倍时,进行扩容)。
扩容增量是原容量的 1 倍,扩展后的新容量为原容量的2倍。

如:HashSet的容量为16,一次扩容后是容量为32

3、HashSet添加元素

3.1、什么是hashCode

hashCode就是对象的散列码,是根据对象的某些信息推导出的一个整数值,默认情况下表示是对象的存储地址。通过散列码,可以提高检索的效率,主要用于在散列存储结构中快速确定对象的存储地址,如Hashtable、hashMap中。

hashCode详细可以看另一篇博客hashCode 以及 hashCode()与equals()的联系

3.2、HashSet如何检查重复?HashSet是如何保证数据不可重复的?

向HashSet 中add ()元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较。
HashSet 中的add ()方法会使用HashMap 的put()方法。
HashMap 的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为HashMap 的key,并且在HashMap中如果K/V相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复(HashMap 比较key是否相等是先比较hashcode 再比较equals )。

是HashSet 部分源码:

private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
// 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值
return map.put(e, PRESENT)==null;
}

hashCode()与equals()的相关规定:

1.如果两个对象相等,则hashcode一定也是相同的
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值
2. 两个对象相等,对两个equals方法返回true
3. 两个对象有相同的hashcode值,它们也不一定是相等的
4. 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个
对象无论如何都不会相等(即使这两个对象指向相同的数据)。

3.3、HashSet与HashMap的区别

HashMapHashSet
实现了Map接口实现Set接口
存储键值对仅存储对象
调用put() 向map中添加元素调用add()方法向Set中添加元素
HashMap使用键(Key)计算HashcodeHashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
HashMap相对于HashSet较快,因为它是使用唯一的键获取对象HashSet较HashMap来说比较慢

二、TreeSet

public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable

TreeSet继承自Set接口,有序、不可重复的,线程不安全。
TreeSet中的元素默认按照自然升序排列。
TreeSet底层是TreeMap实现的,添加的数据存入了map的 key 的位置,而value则固定是PRESENT

1、自定义排序

如果程序员想定义自己的排序方式,方法也很简单,就是让加入 TreeSet 集合中的对象所属的类实现 Comparable 接口,通过实现 compareTo(Object o)方法,达到排序的目的。
假设有这样的需求,学生对象有两个属性,分别是学号和姓名。希望将这些学生对象加入TreeSet 集合后,按照学号大小从小到大进行排序,学号相同的再按照姓名自然排序。来看学生类的代码(实现 Comparable 接口):

class Student implements Comparable {
	int stuNum =-1; //学生学号
	String stuName =""; //学生姓名
	Student(String name, int num){
		this.stuNum = num;
		this.stuName = name;
	}
	//返回该对象的字符串表示,利于输出
	public String toString() {
		return "学号为:"+ stuNum +"的学生,姓名为:"+ stuName;
	}
	//实现 Comparable 的 compareTo 方法
	public int compareTo(Object o){
		Student input =(Student) o;
		//此学生对象的学号和指定学生对象的学号比较
		//此学生对象学号若大则 res 为 1,若小则 res 为-1,相同的话 res =0
		int res = stuNum > input.stuNum?1:(stuNum == input.stuNum?0:-1);
		//若学号相同,则按照 String 类自然排序比较学生姓名
		if(res == O){
			res = stuName.compareTo(input.stuName);
		}
		return res;
	}
}

其中,int compareTo(Object o)方法是用此对象和指定对象进行比较的,如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。编写测试程序,具体代码如下。

public class TestTreeSet2{
	public static void main(String[] args){
	//用有序的 TreeSet 存储学生对象
	Set stuTS = new TreeSetO;
	stuTS.add(new Student("王云",1));
	stuTS,add(new Student("南天华",3));
	stuTS,add(new Student("刘静涛",2));
	stuTS,add(new Student("张平",3));
	//使用迭代器循环输出
	Iterator it=stuTS.iterator();
	while(it.hasNext()){
		System.out.println(it.next());
	}
结果输出

学号为:1的学生,姓名为:王云
学号为:2的学生,姓名为:刘静涛
学号为:3的学生,姓名为:南天华
学号为:3的学生,姓名为:张平

标签:Set,Java,HashMap,HashSet,对象,学号,hashCode,详解,Student
来源: https://blog.csdn.net/X_lsod/article/details/120586888

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有