三种常用Set:HashSet、LinkedHashSet、TreeSet

  set类继承关系:

    

  概述

    Set是对对应Map的一种封装,Set中的元素不可以重复。

    HashSet对应 HashMap、LInkedHashSet对应LinkedHashMap、TreeSet对应TreeMap

   HashSet特点

    1 不保证set的迭代顺序,特别是它不保证该顺序恒久不变;

    2 不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个private static final Object PRESENT = new Object();

    3 非线程安全的;

    4 HashSet通过iterator()返回的迭代器是fail-fast的(参考http://www.cnblogs.com/chenssy/p/3870107.html)。

  HashSet源码分析,LInkedHashSet和TreeSet类似

    成员变量

    两个重要的成员变量:map、PRESENT

    1)map:HashSet基于一个HashMap实现;

    2)PRESENT:作为HashMap中的value;

 public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map;
//定义一个"虚拟"的static final Object对象作为HashMap的value
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

    构造函数

    //构造函数,即新建一个HashMap,默认初识容量为16,加载因子为0.75。
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
。。。

    查找

      HashSet提供了contains(Object o)查看是否包含指定元素的方法,其底层调用的是HashMap.containsKey(Object key)判断是否包含指定key。

     //Set是否含有元素o,即map中是否含有该key
public boolean contains(Object o) {
return map.containsKey(o);
}

    添加

      HashSet提供了add(E e)添加元素的方法,其调用的是底层HashMap中的put(K key, V value)方法,首先判断元素(也就是key)是否存在,如果不存在则插入,如果存在则不插入,这样HashSet中就不存在重复值。

    //如果此set中尚未包含指定元素,则添加指定元素
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

      底层:当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该值确定对象在HashSet中的存储位置。在HashSet中,不能同时存放两个相等的元素,而判断两个元素相等的标准是两个对象通过equals方法比较相等并且两个对象的HashCode方法返回值也相等。

      注意:对于HashSet中保存的对象,请注意正确重写其equals和hashCode方法,以保证放入的对象的唯一性。

    清空与删除

 //如果指定元素存在于此set中,则将其移除
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
} //从此set中移除所有元素
public void clear() {
map.clear();
}

    其他

     //返回此set中的元素的数量
public int size() {
return map.size();
} //如果此set不包含任何元素,则返回 true
public boolean isEmpty() {
return map.isEmpty();
} //返回此 HashSet实例的浅表副本
@SuppressWarnings("unchecked")
public Object clone() {
try {
HashSet<E> newSet = (HashSet<E>) super.clone();
newSet.map = (HashMap<E, Object>) map.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}

    迭代器

     //返回对此 set中元素进行迭代的迭代器
public Iterator<E> iterator() {
return map.keySet().iterator(); //HashMap.keySet()返回<key, value>对中的key集
}

参考资料

https://www.cnblogs.com/CherishFX/p/4790735.html

Java数据结构-------Set的更多相关文章

  1. Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用

    Java数据结构之---Queue队列 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在 ...

  2. JAVA数据结构系列 栈

    java数据结构系列之栈 手写栈 1.利用链表做出栈,因为栈的特殊,插入删除操作都是在栈顶进行,链表不用担心栈的长度,所以链表再合适不过了,非常好用,不过它在插入和删除元素的时候,速度比数组栈慢,因为 ...

  3. Java数据结构之树和二叉树(2)

    从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...

  4. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  5. Java数据结构之线性表(2)

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  6. Java数据结构之线性表

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  7. java 数据结构 图

    以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客,主要是在自己理解的基础上进行记录. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示 ...

  8. java 数据结构 队列的实现

    java 数据结构队列的代码实现,可以简单的进行入队列和出队列的操作 /** * java数据结构之队列的实现 * 2016/4/27 **/ package cn.Link; import java ...

  9. java 数据结构 栈的实现

    java数据结构之栈的实现,可是入栈,出栈操作: /** * java数据结构之栈的实现 * 2016/4/26 **/ package cn.Link; public class Stack{ No ...

  10. Java数据结构和算法

    首先,本人自学java,但是只学习了java的基础知识,所以想接下来学习一下数据结构和算法,但是找了很多教材,大部分写的好的都是用c语言实现的,虽然知道数据结构和算法,跟什么语言实现的没有关系,但是我 ...

随机推荐

  1. Oracle数据库学习(一)

    Oracle数据库由甲骨文公司开发,是基于对象的关系型数据库:下面是简单的学习数据库操作等知识. 1.SQL单表查询(设一个表名为tab) (1)查询所有记录 select * from tab(一般 ...

  2. nodejs fs路径

    引用:https://www.cnblogs.com/guangzhou11/p/7705257.html require()别的js文件的时候,将执行那个js文件. 注意: require()中的路 ...

  3. linux三剑客之sed深度实践

    参数: -a:追加文本到指定行后 -i:插入文本到指定行前 1.单行增加 [root@redhat~]#   sed  ' 2a  6,f '  linux.tet 1,a 2,b 6,f 3,c 4 ...

  4. aop配置问题引发的报错

    今天在使用注解配置aop时出现了几次的错误 INFO - Refreshing org.springframework.context.support.ClassPathXmlApplicationC ...

  5. hashlib模块常用功能

    什么是hash hash是一种算法,该算法接受传入的内容,经过运算得到一串hash值 如果把hash算法比喻为一座工厂 那传给hash算法的内容就是原材料 生成的hash值就是生产出的产品 2.为何要 ...

  6. Linux清空mysql所有数据

    1,删除data目录下所有文件 rm -rf /usr/local/mysql5/data/* 2,mysql_install_db脚本初始化Mysql /usr/local/mysql5/scrip ...

  7. 动态规划:最长上升子序列之基础(经典算法 n^2)

    解题心得: 1.注意动态转移方程式,d[j]+1>d[i]>?d[i]=d[j]+1:d[i] 2.动态规划的基本思想:将大的问题化为小的,再逐步扩大得到答案,但是小问题的基本性质要和大的 ...

  8. Harbor HA部署-使用Ceph RADOS后端

    1. 前言 Harbor 1.4.0版本开始提供了HA部署方式,和非HA的主要区别就是把有状态的服务分离出来,使用外部集群,而不是运行在本地的容器上.而无状态的服务则可以部署在多个节点上,通过配置上层 ...

  9. loj2035 「SDOI2016」征途

    学了斜率优化这题就能一气呵成地做出来啦qwqqwq #include <iostream> #include <cstdio> using namespace std; typ ...

  10. Asp.net自定义控件开发任我行(3)-Render

    摘要 上一篇我们讲到了自定义标签TagPrefix用法,此篇我们来讲一下控件的呈现,主要是呈现下拉框 内容 呈现的方法有,Render,RenderControl,RenderChildren,这三个 ...