转载请注明源出处:http://www.cnblogs.com/lighten/p/7427554.html

1.前言

  原本按照顺序应该是list、queue然后就是set的讲解,但是因为set的实现比较容易,但是其容易是建立在map的实现之上才容易的,所以先讲解的map。现在对于set集合,就一次全部介绍完。Set集合特点就是没有重复的内容,其实现是通过map的键来实现的。

2.HashSet

  HashSet的结构就是持有一个HashMap,map的键就是Set的内容,值全部是PRESENT这个对象。

  构造方法都是与HashMap基本一致。

    public Iterator<E> iterator() {
return map.keySet().iterator();
} public int size() {
return map.size();
} public boolean isEmpty() {
return map.isEmpty();
} public boolean contains(Object o) {
return map.containsKey(o);
} public boolean add(E e) {
return map.put(e, PRESENT)==null;
} public boolean remove(Object o) {
return map.remove(o)==PRESENT;
} public void clear() {
map.clear();
}

  其它的方法实在没什么可说明的,都是map的相关方法,看看就可以了。

3.LinkedHashSet

  LinkedHashSet继承自HashSet,其构造方法调用的都是父类HashSet的构造方法:

  可以看出其入参dummy是没有什么用的,只是用来区分调用的是父类的哪个构造参数而已,值是什么无所谓,最终使用的是LinkedHashMap。其它的方法都是父类的方法。也没有什么可说的。顺便一提,LinkedHashMap的特性是其值是有序的,所以LinkedHashSet的迭代器也是有序的,默认是insert顺序,而不是access顺序,具体见LinkedHashMap那章介绍。

4.TreeSet

  LinkedHashSet只能按照先后顺序来进行排序,TreeSet则是按照比较器给的比较规则进行从小到大排序。其实现也就是借助于TreeMap。

  和HashSet的过程基本一致,实现也都是借助TreeMap的相关方法,所以也没有必要介绍了。

5.EnumSet

  EnumSet的实现有些不一样,其并没有使用EnumMap,而是自己实现。这个类还是一个抽象类,里面的方法全是静态方法。

  数据结构就一个枚举类的Class对象,和该枚举类的枚举实例。其构造方法是default域,我们没有办法进行直接创建。不过其静态方法提供的创建对象的能力。主要分为两个方法:noneOf和allOf。

  noneOf的含义有些让人误解,因为枚举实例都放入了EnumSet中啊,为什么还称作是空?实际上仔细看就会明白,这个构造方法中并没有size等方法,所以虽然数组中有内容,但是却返回的大小都是0。allOf调用了抽象方法addAll(),也仅仅是改变了数量而已。先注意,枚举类的实例个数是影响了具体的类。<=64个的时候,使用的是RegularEnumSet,大于的时候是JumboEnumSet。

  初看RegularEnumSet的源码会一脸懵逼,不是说是addAll是计数吗?为什么是位运算?实际上我们要明确一点,枚举类的删除添加修改等操作并不是真正的这么做了,而是打了一个标记而已。这也就解释了RegularEnumSet为什么必须枚举长度小于等于64,因为long类型只能表示64位。超过64位long不能再表示,所以使用另一个类JumboEnumSet来处理,其有个与实例对应的标志位数组(这个数组也不是一般的数组,本质上还是充分利用了long的位数,并没有一个数组位表示一个实例)和计数字段size来处理。

  其它的添加,删除,获取的逻辑都是基于其标志位的内容来处理的,实际上枚举类的实例数组并没有变化。处理逻辑就不再描述,按照位运算一个个去尝试就可以了。RegularEnumSet的long标志表示是从右边开始算第0位,JumboEnumSet的标志位数组long[]的结构是,前64个元素标志位用long数组的第一个表示,和RegularEnumSet实现一样,从右到左计数,再64个用数组中第2个表示,也是从右到左。

  RegularEnumSet:00000000 00000000 00000000 00001111

  对应枚举实例下标:63                 3210

  JumboEnumSet:long[] 数组长度为2

                  long[0]

            11111111 11111111 11111111 11111111

  对应枚举实例下标:   63                               0

                  long[1]

            00000000 00000000 00000000 00001111

  对应枚举实例下标:  127                              64

Java之集合(十五)Set综述的更多相关文章

  1. Java中的集合(十五) Iterator 和 ListIterator、Enumeration

    Java中的集合(十五) Iterator 和 ListIterator.Enumeration 一.Iterator (一).简介 Iterator 是一个接口,它是集合的迭代器.集合可以通过Ite ...

  2. Java进阶(二十五)Java连接mysql数据库(底层实现)

    Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜 ...

  3. Java进阶(三十五)java int与integer的区别

    Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...

  4. “全栈2019”Java多线程第二十五章:生产者与消费者线程详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  5. “全栈2019”Java多线程第十五章:当后台线程遇到finally

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. “全栈2019”Java异常第十五章:异常链详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  7. “全栈2019”Java第八十五章:实现接口中的嵌套接口

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. 201671010140. 2016-2017-2 《Java程序设计》java学习第十五周

    java学习第十五周 Java的GUI界面设计,框架以及主要部件填充,归置,布局管理,在第十一章和第十二章进行了系统的学习,在这两章的知识奠基下,可以简单的构造一个GUI用户界面,在两周的学习后,可以 ...

  9. “全栈2019”Java第七十五章:内部类持有外部类对象

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. 数据库面试sql

    问题一:.有三张表,学生表S,课程表C,学生课程表SC 01:写出建表语句 答: create table s(id integer primary key,name varchar(20)); cr ...

  2. Spark RDD详解

    1.RDD是什么 RDD(Resilient Distributed Dataset):是Spark的核心数据结构,指的是一个只读的.可分区的分布式数据集,这个数据集的全部或部分可以缓存在内存中,在多 ...

  3. 结对编程--四则运算(Java)梅进鹏 欧思良

    结对编程--四则运算(Java)梅进鹏 欧思良 Github项目地址:https://github.com/MeiJinpen/Arithmetic 功能要求 题目:实现一个自动生成小学四则运算题目的 ...

  4. [svn] TortoisSVN的Blam功能

    团队开发中,我们必须要面对多个人对同一个文件进行修改的情况. 多人修改同一文件,往往就会发生很多的问题,或者随着文件中代码的数量不断增加.当我们必须要使用文件中的其他人写的代码,或者代码发生bug之后 ...

  5. WinForm&&DEV知识小结

    -------------------------------------------------------------------------------- 1.父窗体Form1中调用子窗体For ...

  6. C#: 获取当前路径不要用Environment.CurrentDirectory

    网上大把文章写到C#获取当前路径的方法如下: // 获取程序的基目录. System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径. Syste ...

  7. Cesium简介 [转]

    http://www.cnblogs.com/laixiangran/p/4984522.html 一.Cesium介绍 Cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎. ...

  8. Day 42 协程. IO 并发

    一.什么是协程? 是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程切换效率更快了. ...

  9. H - The LCIS on the Tree HDU - 4718

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  10. 用redis统计大量用户的登陆情况[只判断是否活跃]

    有这样的一个场景需求:有上亿的用户,要统计这批用户的登陆情况,例如一周连续登陆,连续三天是是否登陆,一周活跃天数等用户 存在的挑战 数据如何尽可能用小的空间存储 如何能快速获取指定的数据 如果使用文件 ...