一、Set集合简介
Set集合简单来说相当于一个桶,程序可以依次的把多个对象丢进桶中(Set集合)
Set继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,主要有hashSet和TreeSet两大实现类。
二、hashSet
hashSet是Set接口的典型实现,大多数使用Set集合就是使用这个实现类。
hashSet是基于hashmap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75的hashmap。
放入hashSet中的集合元素实际上是由hashmap中的key来保存的,value存储了一个静态的Object对象。
特点:
1、不能保证元素的排列顺序,也就是无序
2、hashSet不是同步的,也就是非线程安全的,为了防止对外不同步,应该在创建的时候使用Collections.synchronizedSet方法来包装Set
代码示意:
1 package collection;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 public class Demo7 {
7 public static void main(String[] args) throws InterruptedException {
8 TestHashSet run2 = new TestHashSet();
9 Thread thread1 = new Thread(run2);
10 Thread thread2 = new Thread(run2);
11 thread1.start();
12 thread2.start();//两个线程对同一个任务里面的Hashset添加数据,验证hashset不是线程安全的。
13 Thread.sleep(100);
14 System.out.println(run2.set.size());//测试结果表明,一般情况下都是超过1000个数据的
15 }
16 }
17 class TestHashSet implements Runnable {
18 // 实现Runnable 让该集合能被多个线程访问
19 Set set = new HashSet();
20
21 // 线程的执行就是插入1000个整数
22 @Override
23 public void run() {
24 for (int i = 0; i < 1000; i++) {
25 set.add(i);
26 }
27 }
28 }
3、集合元素值可以为null
HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构是哈希表。
哈希表:一个元素为链表的数组,综合了数组和链表的优点。
hashSet中add方法解析:
add方法实际上是调用了底层hashMap的put方法。
首先是判断元素Key是否存在,如果不存在那么插入,如果存在,那么不插入。
问:是怎么判断key是否存在呢?
答:当我们向Set对象中添加对象时,首先调用此对象类的hashCode方法,计算出这个对象的哈希值,这个哈希值就相当于具体是那个桶(数组的下标),
再判断,这个桶(下标)的位置有没有已存储对象,如果没有,那么直接存储此对象,如果已存储有对象,则调用equals方法比较两个对象是否相同,相同则不添加,这样也就避免了hashSet中不存在重复值。
hashSet的遍历方式
1 package collection;
2
3 import java.util.HashSet;
4 import java.util.Iterator;
5
6 public class Demo8 {
7 public static void main(String[] args) {
8 HashSet strings = new HashSet<>();
9 strings.add("你好");
10 strings.add("hello");
11 //第一种遍历方式
12 for (String s:strings) {
13 System.out.println(s);
14 }
15 //第二种遍历方式
16 Iterator iterator = strings.iterator();
17 while (iterator.hasNext()){
18 System.out.println(iterator.next());
19 }
20 }
21 }
总结:map是整个HashSet的核心,而PRESENT则是用来造一个假的value来用的。Map有键和值,HashSet相当于只有键,值都是相同的固定值,即PRESENT。
三、TreeSet
首先此集合从名字上来看与树有关,TreeSet也是基于Map来实现,其底层结构为红黑树
与hashSet同理,TreeSet继承AbstractSet类,获得了set集合基础实现操作。
TreeSet中add方法解析:
实际上调用了底层TreeMap的put方法,再put方法中会调用到Compare(Key,Key)方法,进行key大小的比较。
如果比第一个元素大,就存入树结构根的右侧,如果比第一个元素小,就存入树结构根的左侧。
特点:
1、没有重复元素
2、添加,删除元素,判断元素是否存在,效率比较高
3、有序,为了有序,实现了Comparable接口或者通过构造方法提供一个Comparator对象
TreeSet的元素支持两种排序方式:
自然排序:往TreeSet中添加基本类型调用的是TreeSet的无参构造方法,因此是自然排序
1 package collection;
2
3 import java.util.TreeSet;
4
5 public class TreeSetTest {
6 public static void main(String[] args) {
7 //自然排序实现了排序和去重
8 TreeSet treeSet = new TreeSet<>();
9 treeSet.add(11);
10 treeSet.add(13);
11 treeSet.add(12);
12 treeSet.add(12);
13 for (Integer s:treeSet) {
14 System.out.println(s);
15 }
16 }
17 }
根据提供的Comparator进行排序
1 package collection;
2
3 public class Dog implements Comparable{
4 private String name;
5 private int age;
6
7 public Dog(String name, int age) {
8 this.name = name;
9 this.age = age;
10 }
11
12 public String getName() {
13 return name;
14 }
15
16 public int getAge() {
17 return age;
18 }
19
20 @Override
21 public int compareTo(Object o) {
22 return 0;//当返回0时,集合中只有一个元素
23 //return 1;当返回1时,会顺序存储
24 //return -1;当返回-1时,会倒序存储
25 }
26 }
1 package collection;
2
3 import java.util.TreeSet;
4
5 public class TreeSetTest {
6 public static void main(String[] args) {
7 //自然排序实现了排序和去重
8 TreeSet treeSet = new TreeSet<>();
9 Dog dog1 = new Dog("金毛",25);
10 Dog dog2 = new Dog("哈士奇",22);
11 Dog dog3 = new Dog("阿拉斯加",24);
12 Dog dog4 = new Dog("萨摩耶",21);
13 Dog dog5 = new Dog("柴犬",20);
14 treeSet.add(dog1);
15 treeSet.add(dog2);
16 treeSet.add(dog3);
17 treeSet.add(dog4);
18 treeSet.add(dog5);
19 for (Dog dog : treeSet) {
20 System.out.println(dog.getName()+"---"+dog.getAge());
21 }
22 }
23 }
问:为什么返回0,只会存一个元素,返回-1会倒序存储,返回1会怎么存就怎么取呢?
答:当返回结果为0时:元素值每次比较都认为是相同的元素,这时就不再插入新元素。
答:当返回结果为1时:元素值每次比较,都认为新插入的元素比上一个元素大,于是二叉树存储时,会存入根的右侧,读取时就是正序
当返回结果为-1时:元素值每次比较,都认为新插入的元素比上一个元素小,于是二叉树存储时,会存再根的左侧,读取时就是倒序
元素是如何存储进去的?
总结,TreeSet底层是二叉树结构,红黑树是一种自平衡的二叉树。对add新对象按照指定的顺序进行排序,每增加一个对象都会进行排序,将对象插入到二叉树指定的位置。
使用场景分析:HashSet是基于hash算法实现的,其性能通常是优于TreeSet,为了快速查找而设计的,通常应该使用HashSet,在需要排序的功能时才使用TreeSet。
Original: https://www.cnblogs.com/zhangbinlin/p/16422837.html
Author: ~淡~然~
Title: Set集合
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/590475/
转载文章受原作者版权保护。转载请注明原作者出处!