Set集合

一、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时:元素值每次比较都认为是相同的元素,这时就不再插入新元素。

Set集合

答:当返回结果为1时:元素值每次比较,都认为新插入的元素比上一个元素大,于是二叉树存储时,会存入根的右侧,读取时就是正序

Set集合

当返回结果为-1时:元素值每次比较,都认为新插入的元素比上一个元素小,于是二叉树存储时,会存再根的左侧,读取时就是倒序

Set集合

元素是如何存储进去的?

Set集合

总结,TreeSet底层是二叉树结构,红黑树是一种自平衡的二叉树。对add新对象按照指定的顺序进行排序,每增加一个对象都会进行排序,将对象插入到二叉树指定的位置。

使用场景分析:HashSet是基于hash算法实现的,其性能通常是优于TreeSet,为了快速查找而设计的,通常应该使用HashSet,在需要排序的功能时才使用TreeSet。

Original: https://www.cnblogs.com/zhangbinlin/p/16422837.html
Author: ~淡~然~
Title: Set集合

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/590475/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring学习记录

    1.IOC控制翻转 英文全称 Inversion of control,还有个名称叫依赖注入 Dependency injection ,Spring框架核心容器就是基于这个反向控…

    Java 2023年5月30日
    079
  • Spring——注解@Bean和@Autowired的关系

    关系: @Bean 告诉 Spring:”这是这个类的一个实例,请保留它,并在我请求时将它还给我”。 @Autowired 说:”请给我一个这个…

    Java 2023年5月30日
    064
  • AQS学习(一)自旋锁原理介绍(为什么AQS底层使用自旋锁队列?)

    1.什么是自旋锁? 自旋锁作为锁的一种,和互斥锁一样也是为了在并发环境下保护共享资源的一种锁机制。在任意时刻,只有一个执行单元能够获得锁。 互斥锁通常利用操作系统提供的线程阻塞/唤…

    Java 2023年6月8日
    072
  • 全量同步Elasticsearch方案之Canal

    一、前言 Canal 是阿里的一款开源项目,纯 Java 开发。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了 MySQL(也支持 mariaDB)。 Ca…

    Java 2023年6月6日
    080
  • nginx 视频流

    文件推流测试 > ffmpeg -re -i C:\Users\16418\Desktop\test.mp4 -vcodec copy -loop -1 -c:a aac -…

    Java 2023年5月30日
    070
  • 船舱订票系统测试

    package com.dong.mytest.demo.other.yan; import java.util.ArrayList; import java.util.HashM…

    Java 2023年6月5日
    085
  • 如何搭建一个WEB服务器项目(一)—— 开篇 ,搭建SSH整合框架

    使用Intellij IDEA2019创建SSH(Spring+SpringMVC+Hibernate+Maven整合)项目 观前提示:本系列文章有关服务器以及后端程序这些概念,我…

    Java 2023年6月8日
    0102
  • 设计模式 14 模板模式

    模板模式(Template Pattern)属于 行为型模式 在生活中常常会遇到这样的情况,做某一件事情,有些步骤是固定的,有些步骤的变化的。 比如去医院看病, 挂号和 排队这两个…

    Java 2023年6月6日
    072
  • Java(7)大数

    如果基本的整数和浮点数精度不能够满足需求,那么可以使用 java.math包中两个很有用的类: BigInteger和 BigDecimal。这两个类可以处理包含任意长度数字序列的…

    Java 2023年6月9日
    059
  • Spring5完整版详解

    1、Spring 1.1简介 2002,首次退出来Spring框架的雏形:interface21框架 Spring框架即以interface21框架为基础,经过重新设计,并不断丰富…

    Java 2023年6月14日
    052
  • Java7之后的intern

    最近在《深入理解Java虚拟机》一书中了解到,以下内容在Java7中第一个返回true,第二个返回false,产生了一些疑惑,经过一番搜索,对intern的理解有所加深,这里记一下…

    Java 2023年5月29日
    072
  • Aviator和MVEL实现Map过滤(通过动态表达式求值)—Java表达式引擎的使用

    pom com.googlecode.aviator aviator 4.2.10     org.mvel     mvel2     2.4.10.Final View Cod…

    Java 2023年5月29日
    072
  • java package(包)的用法

    一般来说都用eclipse自动化图形工具搞定,我用的是ubuntu,所以需要自己打包引入。 什么是包? 这是对java源代码的组织和管理的一种方式,比如:当操作系统某个目录的文件非…

    Java 2023年5月29日
    087
  • 物联网架构成长之路(56)-SpringCloudGateway+JWT实现网关鉴权

    0. 前言结合前面两篇博客,前面博客实现了Gateway网关的路由功能。此时,如果每个微服务都需要一套帐号认证体系就没有必要了。可以在网关处进行权限认证。然后转发请求到后端服务。这…

    Java 2023年5月30日
    083
  • Gradle连载4-依赖包打包方式

    一、apply方法的使用 apply&#xA0;<span class="hljs-string">plugin:</span>…

    Java 2023年6月13日
    0103
  • 【Redis】简单动态字符串SDS

    C语言字符串 char *str = "redis"; // 可以不显式的添加\0,由编译器添加 char *str = "redis\0"…

    Java 2023年6月8日
    098
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球