集合简称集,是数学中一个基本的概念,主要体现两方面的特征:1)一个集合中,任何两个元素都可以认为是不相同的,即为每个元素只能出现一次。2)一个集合中,每个元素的地位都是相同的,元素之间是无序的。Set集合是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。Set接口主要实现了两个实现类:HashSet类按照哈希算法来存取集合中的对象,存取速度比较快;TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。Set集合不允许包含相同的元素,如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。Set接口是没有所谓的有序和无序的概念,TreeSet是有序的,但此有序是说读取数据的顺序和插入的数据的顺序一致。HashSet中无序是指读取数据的顺序不一定和插入数据的顺序一样。但是HashSet真实的情况是有序的,只不过它是通过内部HashCode方法计算hash值后自动进行了排序,所以读取的是经过内部排序后的数据,且此数据每次结果都是一样的顺序。1)不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化;同样的,HashMap和HashSet是一样的,HashMap是根据key的hash值进行了排序。HashSet底层是基于HashMap实现的,HashSet存放的数据实际就是HashMap的key,而HashMap的value存放的是一个静态的final对象PERSENT;当调用HashSet无参构造函数的时候,实际只是实例化了HashMap对象。
推荐下自己做的 Spring Cloud 的实战项目:https://gitee.com/yoodb/jingxuan-springcloud
HashSet源码,无参构造函数如下:
public HashSet() {
//实例化map成员变量
map = new HashMap<>();
}
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精选”(w_z90110),专注Java技术干货分享!让你从此路人变大神!回复关键词领取资料:如Mysql、Hadoop、Dubbo、Spring Boot等,免费领取视频教程、资料文档和项目源码。微信搜索小程序“Java精选面试题”,内涵3000+道Java面试题!