一、Set 接口概述

  1、Set 接口是 Collection 的子接口,set 接口没有提供额外的方法;

  2、Set接口:存储无序的、不可重复的数据,Set 接口中会以某种规则保证存入的元素不出现重复

  3、Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个  Set 集合中,则添加操作失败;

  4、Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法;

  5、Set 集合不是同步的,多线程不安全的;

  6、Set 接口的结构

    

   特点查询速度快,不重复,没有索引。

二、常用实现类

  1、HashSet

    HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值。

    构造方法:

HashSet() :构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75

     源码:

    

  2、LinkedHashSet

    作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet。

    构造方法:

LinkedHashSet(): 构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set
LinkedHashSet(int initialCapacity) :构造一个带指定初始容量和默认加载因子 (0.75) 的新空链接哈希 set

    源码:

    

    

  3、TreeSet

    TreeSet:可以按照添加对象的指定属性,进行排序,底层使⽤红⿊树,能够按照添加元素的顺序进⾏排序,排序的⽅式有⾃然排序和定制排序。

    构造方法:

TreeSet() :构造一个新的空 set,该 set 根据其元素的自然顺序进行排序
TreeSet(Comparator<? super E> comparator) :构造一个新的空 TreeSet,它根据指定比较器进行排序

 

    源码:

    

 

  4、小结

    (1)Set 的内部实现其实是一个 Map,即HashSet的内部实现是一个HashMap,TreeSet的内部实现是一个TreeMap,LinkedHashSet的内部实现是一个LinkedHashMap。

    (2)但是 Set 中只有一个元素,又是怎么变成(key,value)的呢?

      以 HashSet 的 add 方法为例:

    原来是,把添加到 Set 中的元素作为内部实现 map 的 key,然后用一个常量对象 PRESENT 对象,作为value。

    所有的 HashSet 共用同一个PRESENT对象,所有的 TreeSet 共用同一个 PRESENT对象,所有的 LinkedHashSet 共用同一个 PRESENT 对象。

    这是因为 Set 的元素不可重复和 Map 的 key 不可重复有相同特点。Map 有一个方法 keySet() 可以返回所有 key。

 

三、实现类的对比

  1、Set 集合是有序的吗?

    ① 如果按照元素的存储顺序来说,有一些是可以保证的,有一些是不能保证的。唯有 LinkedHashSet可以保证元素添加的顺序

    ② 如果按照元素的大小顺序来说,有一些是可以保证的,有一些是不能保证的。唯有 TreeSet可以保证元素的大小顺序

    ③ HashSet:既不能保证添加顺序,也不能保证大小顺序。是完全无序的。

  2、HashSet 与 LinkedHashSet 区别?

    HashSet:完全无序。

    LinkedHashSet:是按照添加顺序来存储的。LinkedHashSet 是 HashSet 的子类,比 HashSet 多维护了添加的顺序。

    当既想要实现集合的元素的不可重复性,又想要保证元素的添加顺序,就选择使用LinkedHashSet(效率低),否则就用List系列或HashSet。

  3、HashSet 与 TreeSet 的区别?

    HashSet:完全无序。

    TreeSet:是按照存储元素的大小来排序,当你需要元素不可重复,又要给元素排大小时,就用TreeSet。

    注意:要用到TreeSet,存储的元素对象一定要实现 要用到TreeSet,一定要用java.lang.Comparable或java.util.Comparator

  3、如何保证元素不可重复的呢?(如何判断两个元素是重复的呢)

    (1)HashSet 和 LinkedHashset 集合:

        ① 先比较元素的 hash 值,如果 hash 值不一样,说明两个元素一定不相同。

        ② 如果 hash 值一样,再调用 equals 方法比较

    (2)TreeSet 集合:

       按照存储元素的大小来决定元素是否相同,如果两个元素大小“相等”就是相同的元素。即必须实现 java.lang.Comparable或java.util.Comparator。

 

四、Set 的无序性与不可重复的理解

  1、无序性

    无序性:不等于随机性。⽆序性是指存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。

  2、不可重复性

    不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。

    不可重复性是指添加的元素按照 equals()判断时 ,返回 false,需要同时重写 equals()⽅法和 HashCode()⽅法。

  3、

四、Set 中方法

  Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法。

  

 

五、如何保证数据的一致性(不可重复性)?

  要求:向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()

  要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码

  重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

 

posted on 2021-04-19 10:46  格物致知_Tony  阅读(112)  评论(0编辑  收藏  举报