【194期】HashSet 是无序的吗?为什么输出的结果有序?

点击上方“Java精选”,选择“设为星标”

别问别人为什么,多问自己凭什么!

下方有惊喜,留言必回,有问必答!

每天 08:15 更新文章,每天进步一点点...

什么是集合?

集合简称集,是数学中一个基本的概念,主要体现两方面的特征:

1)一个集合中,任何两个元素都可以认为是不相同的,即为每个元素只能出现一次。

2)一个集合中,每个元素的地位都是相同的,元素之间是无序的。

什么是Set集合?

Set集合是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。Set接口主要实现了两个实现类:HashSet类按照哈希算法来存取集合中的对象,存取速度比较快;TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。

Set集合不允许包含相同的元素,如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。

Set接口是没有所谓的有序和无序的概念,TreeSet是有序的,但此有序是说读取数据的顺序和插入的数据的顺序一致。

HashSet无序吗?

HashSet中无序是指读取数据的顺序不一定和插入数据的顺序一样。但是HashSet真实的情况是有序的,只不过它是通过内部HashCode方法计算hash值后自动进行了排序,所以读取的是经过内部排序后的数据,且此数据每次结果都是一样的顺序。

简单说一说哈希表

一个元素为链表的数组,综合了数组与链表的优点。

HashSet具有以下特点:

1)不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化;

2)HashSet不是同步的;

3)集合元素值可以是null。

同样的,HashMap和HashSet是一样的,HashMap是根据key的hash值进行了排序。

HashSet底层是基于HashMap实现的,HashSet存放的数据实际就是HashMap的key,而HashMap的value存放的是一个静态的final对象PERSENT;当调用HashSet无参构造函数的时候,实际只是实例化了HashMap对象。

HashSet源码,无参构造函数如下:

public HashSet() {
        //实例化map成员变量
        map = new HashMap<>();
}

推荐下自己做的 Spring Cloud 的实战项目:

https://gitee.com/yoodb/jingxuan-springcloud

HashSet集合中,假如自然数或字符串(单字符或多字符)输出是有序还是无序呢?

public class JingXuanApplication {
	public static void main(String[] args) throws Exception {
        Random ran = new Random();
        Set<Integer> set = new HashSet<>();
        while(set.size() < 20) {
        	set.add(ran.nextInt(20)+1);
        }
        for (Integer integer : set) {
			System.out.println(integer);
		}
	}
}

当按照上述代码插入数据后,发现读取出来的数据如下方输出结果顺序,这是因为正好插入数据的hash值是按照这个顺序排列的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

从上面输出结果,单一自然数输出是有序的。那么当插入一个多位的数值时会出现什么样的变化呢?

public class JingXuanApplication {
	public static void main(String[] args) throws Exception {
        Random ran = new Random();
        Set<Integer> set = new HashSet<>();
        while(set.size() < 20) {
        	set.add(ran.nextInt(2000)+1);
        }
        for (Integer integer : set) {
			System.out.println(integer);
		}
	}
}

输出结果则每次都不会相同,此次输出结果如下:

1280
1345
419
1861
1317
135
1704
1770
171
1835
588
1298
498
178
597
408
954
1114
1725
1790

总结

Set的实现类HashSet底层是基于HashMap实现的,HashSet存储的元素对应hashMap的key,因为HashMap不能存储重复的Key,所以HashSet不能存放重复元素;由于HashMap的key是基于hashCode存储对象的,所以HashSet中存放的对象也是无序的;HashSet也没有提供get方法,可以通过Iterator迭代器获取数据。

HashSet中元素是按照它们的HashCode值排序存储的,hash算法混淆程度低,在[0, 2^32-1]范围内经过HashMap.hash()之后还是得到之前的结果。

对于单个字符而言,这些HashCode是按照ASCII码,因此,当按顺序添加自然数或者26个英文字符时,会产生一种HashSet也可以有序输出“错觉”的假象。

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

------ THE END ------

a5c5b48b9dce83cbb9e55ef538ce8805.png精品资料,超赞福利!4b2bd5f321ebc1389b81dbec990861f7.png

>Java精选面试题<
3000+ 道面试题在线刷,最新、最全 Java 面试题!

27c2a77bc5d27523f01aaad63efda237.png

492e639bd7646e4bc22c956461e70b03.png

期往精选  点击标题可跳转

【186期】面试官问:OAuth2 vs JWT,到底怎么选择?

【187期】Java 中的 BigDecimal 运算,如何解决精度丢失问题?

【188期】面试官问:如何防止你的 jar 包被反编译?

【189期】利用 Fastjson 注入 Spring MVC 内存马,太秀了~!

【190期】对 volatile 的理解—从 JMM 以及单例模式剖析

【191期】Redis 延时任务详细解读,高手养成篇

【192期】面试官问:说说 Tomcat 组成与工作原理?

【193期】为什么要使用注册中心?是 Eureka 还是 Nacos?

6ec6624e9f42a61ab06e57a5147dd723.png技术交流群!27f7fae69963b0dc0a692789d6780b89.png

最近有很多人问,有没有读者&异性交流群,你懂的!想知道如何加入。加入方式很简单,有兴趣的同学,只需要点击下方卡片,回复“加群”,即可免费加入交流群!

文章有帮助的话,在看,转发吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值