HashSet

HashSet继承AbstractSet类,实现Set、Cloneable、Serializable接口。其中AbstractSet提供Set接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。Set接口是一种不包括重复元素的Collection。HashSet是无序的,不能保证迭代的次序。可以存储null值,同时是线程不安全的,底层实现是HashMap。

public class HashSet

extends AbstractSet

implements Set, Cloneable, java.io.Serializable

构造器

/**

* 创建一个空的set,起底层的HashMap的默认初始容量为16,默认的加载因子为0.75

* default initial capacity (16) and load factor (0.75).

*/

public HashSet() {

map = new HashMap<>();

}

/**

* 创建一个包含指定集合中元素的set。

* 其底层的HashMap使用默认负载因子(0.75)和足以容纳指定集合中的元素的初始容量创建的

* 其初始容量的计算公式为Math.max((int) (c.size()/.75f) + 1, 16),c即为传入集合的大小

* @param c the collection whose elements are to be placed into this set

* @throws NullPointerException if the specified collection is null

*/

public HashSet(Collection extends E> c) {

map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));

addAll(c);

}

/**

* 创建一个空的set,其底层的HashMap的容量为指定的容量initialCapacity,

* 加载因子为指定的loadFactor

* @param initialCapacity the initial capacity of the hash map

* @param loadFactor the load factor of the hash map

* @throws IllegalArgumentException if the initial capacity is less

* than zero, or if the load factor is nonpositive

*/

public HashSet(int initialCapacity, float loadFactor) {

map = new HashMap<>(initialCapacity, loadFactor);

}

/**

* 创建一个空的set,其底层的HashMap的容量为指定的容量initialCapacity,

* 加载因子为默认的0.75

* @param initialCapacity the initial capacity of the hash table

* @throws IllegalArgumentException if the initial capacity is less

* than zero

*/

public HashSet(int initialCapacity) {

map = new HashMap<>(initialCapacity);

}

容量 * 加载因子=threshold,为这个容器的临界值,当存储的元素到了这个临界值,那么容器就会自动扩容。

方法

public boolean add(E e) {

return map.put(e, PRESENT)==null;

}

?该方法的作用是:如果指定的元素尚不存在,则将其添加到该集合中。可以看到add方法的底层实现是将指定的元素存入到声明的HashMap中,将元素值作为map的key,然后指定一个PRESENT作为value。

?这个value值是一个常量,所有添加到set中的元素,最终添加到对应的hashmap中的时候,对应的value都是PRESENT:

private static final Object PRESENT = new Object();

?添加到set的元素实际存储到了map的key中,这也能够保证存入到set中的元素不会重复。

public Iterator iterator() {

return map.keySet().iterator();

}

? iterator()方法返回对此 set 中元素进行迭代的迭代器。返回元素的顺序并不是特定的。底层调用HashMap的keySet返回所有的key,这点反应了HashSet中的所有元素都是保存在HashMap的key中,value则是使用的PRESENT对象,该对象为static final。

public int size() {

return map.size();

}

size()返回此 set 中的元素的数量(set 的容量)。底层调用HashMap的size方法,返回HashMap容器的大小。

public boolean contains(Object o) {

return map.containsKey(o);

}

?contains(),判断某个元素是否存在于HashSet()中,存在返回true,否则返回false。

public Object clone() {

try {

HashSet newSet = (HashSet) super.clone();

newSet.map = (HashMap) map.clone();

return newSet;

} catch (CloneNotSupportedException e) {

throw new InternalError();

}

}

clone返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。

LinkedHashSet

?LinkedHashSet继承自HashSet,源码更少、更简单,唯一的区别是LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。

public class LinkedHashSet

extends HashSet

implements Set, Cloneable, java.io.Serializable {

?其内部的构造方法:

public LinkedHashSet(int initialCapacity, float loadFactor) {

super(initialCapacity, loadFactor, true);

}

public LinkedHashSet(int initialCapacity) {

super(initialCapacity, .75f, true);

}

public LinkedHashSet() {

super(16, .75f, true);

}

public LinkedHashSet(Collection extends E> c) {

super(Math.max(2*c.size(), 11), .75f, true);

addAll(c);

}

?LinkedHashSet的父类是HashSet,其构造方法中调用的父类构造方法super,指的就是HashSet中这个默认访问权限的构造器:

HashSet(int initialCapacity, float loadFactor, boolean dummy) {

map = new LinkedHashMap<>(initialCapacity, loadFactor);

}

?可以看出LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。

?LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。

TreeSet

?TreeSet会对集合里的元素按照指定的顺序进行排序,它的底层数据结构依据的是红-黑二叉树。如果想要往TreeSet集合中存入自定义类型的元素,有两种方案:

?1、(自然排序)这个元素对应的类要么自身实现了Comparable接口,重写了其中的compareTo方法,在方法内定义比较算法, 根据大小关系, 返回正数负数或零,在使用TreeSet存储对象的时候, add()方法内部就会自动调用compareTo()方法进行比较, 根据比较结果使用二叉树形式进行存储。TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复,不存储。

?2、自定义一个比较器类,继承Comparator,定义存入集合的元素是如何比较的。TreeSet,它根据指定比较器进行排序。插入到该set的所有元素都必须能够由指定比较器进行相互比较:对于set中的任意两个元素e1和e2,执行 comparator.compare(e1, e2) 都不得抛出 ClassCastException。如果用户试图将违反此约束的元素添加到 set 中,则add调用将抛出ClassCastException。

?如果存入集合的元素既不支持自身比较性,又没有为这个集合传入自定义的比较器对象,那么就会抛出异常:

Exception in thread "main" java.lang.ClassCastException: com.test2.B cannot be cast to java.lang.Comparable

?TreeSet是非同步的。TreeSet实际上是TreeMap实现的。TreeSet不支持快速随机遍历,只能通过迭代器进行遍历!

比较HashSet、LinkedHashSet和TreeSet三者的异同

HashSet 是 Set 接口的主要实现类 ,HashSet 的底层是 HashMap,线程不安全的,可以存储null值;

LinkedHashSet 是 HashSet 的子类,底层是LinkHashMap,能够按照添加的顺序遍历;

TreeSet 底层使用红黑树,能够按照按照某种规则对元素进行排序,排序的方式有自然排序和定制排序。集合中的元素是有序的,集合中的元素是唯一的。

原文:https://www.cnblogs.com/yxym2016/p/14515119.html

java 实现set,Java--Set的三个具体实现类相关推荐

  1. java源代码实例倒计时_Java倒计时三种实现方式代码实例

    写完js倒计时,突然想用java实现倒计时,写了三种实现方式 一:设置时长的倒计时: 二:设置时间戳的倒计时: 三:使用java.util.Timer类实现的时间戳倒计时 代码如下: package ...

  2. Java 数组转成集合List三种方法和(数组、集合List、Set相互转换)

    Java 数组转成集合List 三种方法 package com.list;import java.util.ArrayList; import java.util.Arrays; import ja ...

  3. 数据结构java 图实验代码_20172329 2018-2019 《Java软件结构与数据结构》实验三报告...

    20172329 2018-2019-2 <Java软件结构与数据结构>实验三报告 课程:<Java软件结构与数据结构>html 班级: 1723java 姓名: 王文彬lin ...

  4. JAVA中用于处理字符串的 三兄弟

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! JAVA ...

  5. Java学习笔记2.1.2 Java基本语法 - Java三种注释方式

    文章目录 零.本讲学习目标 一.注释的作用 二.注释的分类 (一)简单说明 1.单行注释 2.多行注释 3.文档注释 (二)案例演示 (三)注释的嵌套 1.简单说明 2.案例演示 三.养成写注释的良好 ...

  6. java的如何创建js_[Java教程]JS创建事件的三种方式(实例)

    [Java教程]JS创建事件的三种方式(实例) 0 2016-05-11 14:00:16 1.普通的定义方式 οnclick="Sfont=prompt('请在文本框中输入红色','红色' ...

  7. Java学习笔记10(面向对象三:接口)

    接口: 暂时可以理解为是一种特殊的抽象类 接口是功能的集合,可以看作是一种数据类型,是比抽象类更抽象的"类" 接口只描述所应该具备的方法,并没有具体实现,具体实现由接口的实现类(相 ...

  8. Java中 LocalDate、LocalTime、LocalDateTime三个时间工具类的使用介绍

    Java中 LocalDate.LocalTime.LocalDateTime三个时间工具类的使用介绍 一.背景: 之前在做项目的过程中,对日期时间类没有一个系统的了解,总是在用的时候去搜索一下,解决 ...

  9. Java中遍历Set集合的三种方法

    Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...

  10. 决定Java程序员工资高低的三个因素

    因为工资高,吸引了一大批人纷纷加入IT行业.的确,就目前的形势来看,IT行业的平均工资确实高于一般行业,但这并以为只要进入这一行就是高工资,想要获得高工资还是看个人技术和其他因素的. 本篇文章总结了影 ...

最新文章

  1. 在R语言环境中无法载入rJava包的解决办法
  2. 分布式实时日志分析解决方案ELK部署架构
  3. destoon php,DESTOON_7.0_UTF8
  4. 十二、深入Java的循环语句
  5. 趣谈设计模式 | 适配器模式(Adapter):如何让现存对象适用于新的环境?
  6. MediaPlayer对象从停止状态到播放状态调用的方法是prepare()和start()
  7. 剑指offer(C++)-JZ8:二叉树的下一个结点(数据结构-树)
  8. 使用Rufus制作LINUX启动安装U盘(成功)
  9. 【昊鼎王五】Windows的Git客户端安装步骤
  10. iPhone配置实用工具介绍
  11. JS的基本概念和语法
  12. android更改应用图标大小,Android选项菜单:更改图标大小
  13. pdo mysql 函数_PDO函数属性详解
  14. 知道ip获取计算机密码,知道iP地址怎么获取密码
  15. [下载] Windows 10 Version 1809 微软官方原版镜像
  16. 527. Word Abbreviation
  17. 弘辽科技:店铺前期可以不上宝贝吗?店铺如何上宝贝?
  18. atsha204a加密ic01
  19. 升级JDK版本注意事项
  20. Mysql多表查询,获取部门最高工资的sql语句方案

热门文章

  1. PHP网页定时器和跳转页面
  2. a7100换电池_动动手你也行 篇十四:冲动是魔鬼——单反电池换芯失败记
  3. ikm java_2013Morgan Stanley IKM assessment
  4. camunda流程定义表无数据_BPM - 业务流程管理
  5. jq点击按钮获取php的值删除,通过jquery怎么移除点击事件
  6. python中dom模块_Python中使用dom模块生成XML文件示例
  7. c++ websocket客户端_阿里面经WebSocket实时通信
  8. 【uniapp】 class表达式
  9. cglib动态代理和JDK动态代理
  10. python爬取素材图片代码_基于Python爬取素材网站音频文件