一个不包含重复元素的 collection。更确切地讲,set 不包含满足e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素

在所有构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从 Collection 接口所继承的内容。

Set不能包含重复的元素,它的所有方法都是从Collection接口继承的,并且对一些方法加上了相应的限制。Set还增强了equals方法和hasCode方法的可用性,允许对实现类型不一样的实例进行有意义的对比

Set接口定义的方法与Collection一致,在此不再列出,仅对Set的批量操作稍加说明。假设s1和s2都是Set类型,下面给出一些例子

s1.containsAll(s2) — 如果s2是s1的子集,返回true;反之,返回false

s1.addAll(s2) — 将s1和s2的并集存入s1

s1.retainAll(s2) — 将s1和s2的交集存入s1

s1.removeAll(s2) — 移除s1中与s2重合的元素

Java平台提供了三种通用实现类:HashSet,TreeSet和LinkedHashSet。

HashSet用哈希表作为容器,是性能最好的实现类,但是它不保证迭代顺序,元素的顺序不是固定的

TreeSet用红黑树作为容器,根据元素值进行排序,它的效率要比HashSet低很多

LinkedHashSet也是用哈希表实现的,不同的是,哈希表中运行着一个链表,元素按照插入的先后顺序排序。LinkedHashSet的元素顺序比混乱的HashSet要清晰很多,但是效率要比HashSet低

HashSet

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

HashSet除了集合的通用实现类都有的无参构造函数和接受一个Collection作为参数的构造函数,还有两个特殊的构造函数:

HashSet(int initialCapacity)

构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。

HashSet(int initialCapacity, float loadFactor)

构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。

初始容量的默认值为16,加载因子的默认值为0.75

需要注意的是,HashSet不支持Collection接口中定义的批量操作方法,如addAll()、containsAll()、removeAll()、retainAll()

TreeSet

基于 TreeMap 的 NavigableSet接口的实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是定义良好的;它只是违背了 Set 接口的常规协定。

该实现类也有两个特殊的构造方法:

TreeSet(Comparator<?super E> comparator)

构造一个新的空 TreeSet,它根据指定比较器进行排序。

TreeSet(SortedSet<E> s)

构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。

TreeSet扩展方法(即没有在Set接口中定义的方法):

E ceiling(E e)

返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。

Comparator<?super E> comparator()

返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null。

NavigableSet<E> descendingSet()

返回此 set 中所包含元素的逆序视图。

E first()

返回此 set 中当前第一个(最低)元素。

E floor(E e)

返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。

SortedSet<E> headSet(E toElement)

返回此 set 的部分视图,其元素严格小于toElement。

NavigableSet<E> headSet(E toElement,boolean inclusive)

返回此 set 的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement。

E higher(E e)

返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。

E last()

返回此 set 中当前最后一个(最高)元素。

E lower(E e)

返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。

E pollFirst()

获取并移除第一个(最低)元素;如果此set 为空,则返回 null。

E pollLast()

获取并移除最后一个(最高)元素;如果此set 为空,则返回 null。

NavigableSet<E> subSet(E fromElement,boolean fromInclusive, E toElement, boolean toInclusive)

返回此 set 的部分视图,其元素范围从fromElement 到 toElement。

SortedSet<E> subSet(E fromElement, EtoElement)

返回此 set 的部分视图,其元素从fromElement(包括)到 toElement(不包括)。

SortedSet<E> tailSet(E fromElement)

返回此 set 的部分视图,其元素大于等于fromElement。

NavigableSet<E> tailSet(E fromElement,boolean inclusive)

返回此 set 的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement。

需要注意的是TreeSet实现了SortedSet接口,实现了该接口的子类中,视图操作(即subSet、tailSet等方法)与List有很大不同。List的视图操作在源列表修改后将会抛出异常,比如,我们截取一个使用subList方法截取List的一段元素作为操作对象,一旦源List进行了插入、删除等操作,则用subList获取的子列表将会抛出异常。而SortedSet的子类不会出现这种情况,因为使用subSet截取SortedSet的起始点是不是固定的某两个元素,而是其下标的绝对位置,对源集合的修改会同步到子集合当中,反之亦然。另外,Set的视图操作与List一样,是半开放的,即包含低位段,不包含高位段,比如,有一个Set包含的元素为字母a-g,subSet(‘a’,’d’)得到的结果是包含’a’、’b’、’c’的集合

LinkedHashSet

具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不受在set 中重新插入的元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)

此实现可以让客户免遭未指定的、由HashSet 提供的通常杂乱无章的排序工作,而又不致引起与 TreeSet 关联的成本增加。使用它可以生成一个与原来顺序相同的 set 副本,并且与原 set 的实现无关:

     void foo(Set s) {
         Set copy = new LinkedHashSet(s);
         ...
     }

如果模块通过输入得到一个 set,复制这个 set,然后返回由此副本决定了顺序的结果,这种情况下这项技术特别有用。(客户通常期望内容返回的顺序与它们出现的顺序相同。)

扩展的构造方法:

LinkedHashSet(int initialCapacity)

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

LinkedHashSet(int initialCapacity, float loadFactor)

构造一个带有指定初始容量和加载因子的新空链接哈希 set。

该实现类没有扩展的方法,与Set接口中定义的方法一致

集合框架之Set接口的更多相关文章

  1. 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口 1.Map接口概述 Map是一种映射关系,那么什么是映射关系呢? 映射的数学解释 设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在 ...

  2. 第18章 集合框架(2)-Set接口

    第18章 集合框架(2)-Set接口 Set是Collection子接口,模拟了数学上的集的概念 Set集合存储特点 1.不允许元素重复 2.不会记录元素的先后添加顺序 Set只包含从Collecti ...

  3. Java集合框架之Collection接口

    Java是一门面向对象的语言,那么我们写程序的时候最经常操作的便是对象了,为此,Java提供了一些专门用来处理对象的类库,这些类库的集合我们称之为集合框架.Java集合工具包位于Java.util包下 ...

  4. java 集合框架(二)Iterable接口

    Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...

  5. Java集合框架之四大接口、常用实现类

    Java集合框架 <Java集合框架的四大接口> Collection:存储无序的.不唯一的数据:其下有List和Set两大接口. List:存储有序的.不唯一的数据: Set:存储无序的 ...

  6. Java集合框架之Map接口浅析

    Java集合框架之Map接口浅析 一.Map接口综述: 1.1java.util.Map<k, v>简介 位于java.util包下的Map接口,是Java集合框架的重要成员,它是和Col ...

  7. Java集合框架之Set接口浅析

    Java集合框架之Set接口浅析 一.java.util.Set接口综述: 这里只对Set接口做一简单综述,其具体实现类的分析,朋友们可关注我后续的博文 1.1Set接口简介 java.util.se ...

  8. Java集合框架之List接口浅析

    Java集合框架之List接口浅析 一.List综述: 毫无疑问List接口位于java.util包下,继承自 Collection接口 存储元素的特点: 有序可重复(有序:即存进去是什么顺序,取出来 ...

  9. Java集合框架中Map接口的使用

    在我们常用的Java集合框架接口中,除了前面说过的Collection接口以及他的根接口List接口和Set接口的使用,Map接口也是一个经常使用的接口,和Collection接口不同,Map接口并不 ...

  10. Java集合框架中List接口的简单使用

    Java集合框架可以简单的理解为一种放置对象的容器,和数学中的集合概念类似,Java中的集合可以存放一系列对象的引用,也可以看做是数组的提升,Java集合类是一种工具类,只有相同类型的对象引用才可以放 ...

随机推荐

  1. Docker入门之---ENTRYPOINT和CMD

    1. 前言  ENTRYPOINT 和CMD 都是Dockerfile 中的命令,两者都是用来:指定默认的容器的主进程的启动命令.那么接下来就介绍一下这两者在Dockerfile 中,以及Docker ...

  2. [洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)

    题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链.(n<=550, ...

  3. CTSC&APIO2017

    CTSC Day -1 因为越发感到自己与dalao们之间姿势水平的差距,本来打算再多学些姿势,但被老师叫去做noi,于是花了一两周的时间做完了noi2011~2015,也学到了一些奇怪姿势,还是挺有 ...

  4. hdu 5115(2014北京—dp)

    题意: 有一排狼,每只狼有一个伤害A,还有一个伤害B.杀死一只狼的时候,会受到这只狼的伤害A和这只狼两边的狼的伤害B的和.如果某位置的狼被杀,那么杀它左边的狼时就会收到来自右边狼的B,因为这两只狼是相 ...

  5. Linux LCD 显示图片【转】

    转自:https://blog.csdn.net/niepangu/article/details/50528190 BMP和JPEG图形显示程序1)  在LCD上显示BMP或JPEG图片的主流程图首 ...

  6. python raise和assert的区别

    python中raise和assert的区别 一.使用raise抛出异常 python可以自动触发异常,raise(内置函数)的定义为显示的抛出异常,用户可以使用raise进行判断,显式的引发异常,r ...

  7. 某些情况下调用函数为什么要在函数名前加“(void)”

    我们知道,在定义函数时,加在函数名前的"void"表示该函数没有返回值.但在调用时,在函数名前加"(void)"的作用又是什么呢? 最明显的一点就是表示程序并不 ...

  8. Delphi7 ADO面板上的控件简介

    ? ADO Connection的主要方法:1) Begin Trans    开始启动一个新的事务,必须保证数据连接处于激活状态.2) Cancel    关闭于数据库的连接.3) Commit T ...

  9. C语言程序设计第三次作业——选择结构(一)

    (一)改错题 错误信息: 错误原因:y=1/x后没加分号 改正方法:在其后加上分号 错误信息: 错误原因:if语句后接了:,使else语句找不到对应的if 改正方法:删掉if后的分号 错误信息: 错误 ...

  10. flask jQuery ajax 上传文件

    1.html 代码 <div> <form id="uploadForm" enctype="multipart/form-data" > ...