介绍

Set:集合,是一个不包含重复数据的集合。(A collection that contains no duplicate elements. )

set中最多包含一个null元素,否者包含了两个相同的元素,不符合定义。

上一篇学习了Java中的容器类的一些基础接口,以及Collection接口三大分支中的List分支(ArrayList以及LinkedList)。这一篇文章将讲解Collection三大分支(List、Set、Queue)中的Set分支,以及衍生出来的子类。

java容器类分析:Collection,List,ArrayList,LinkedList深入解读

Set接口的总的集成关系如下图:


Set接口

public interface Set<E> extends Collection<E>

查看Set的源码可以发现,Set中的接口函数和Collection完全相同,并没有添加任何新的接口。只是子类在实现这些接口的时候需要考虑,Set中不能有重复的元素这一原则。接口中的函数及描述可查看上一篇博客。


AbstractSet抽象类

和AbstractList及AbstractCollection的作用相似,AbstractSet类作为一个抽象类,实现了Set接口中的部分函数,减少后续Set子类的实现工作。

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>

具体该抽象类实现了Set中的如下几个接口:
 public boolean equals(Object o) {
if (o == this)
return true; if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {

return containsAll(c);

        } catch (ClassCastException unused)   {
return false;
} catch (NullPointerException unused) {
return false;
}
}

hashCode():Set的hash值等于将Set中所有元素的hash值相加,这就保证了if(set1.equals(set2)) 那么set1.hashCode()== set2.hashCode()。

public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}

removeAll(): 移除c与当前Set的交集,返回值代表是否有元素从当前Set中移除,交集为空返回false否则返回true。

public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false; if (size() > c.size()) {
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}

SortedSet


public interface SortedSet<E> extends Set<E>


public interface SortedSet<E> extends Set<E> {//经过某种排序的set       JDK1.7   java.util  

    Comparator<? super E> comparator();//返回对此 set中的元素进行排序的比较器
SortedSet<E> subSet(E fromElement, E toElement);//返回此 set的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。(
SortedSet<E> headSet(E toElement);//返回此 set 的部分视图,其元素严格小于 toElement
SortedSet<E> tailSet(E fromElement);//返回此 set的部分视图,其元素大于等于 fromElement
E first();//set中第一个元素
E last();//set中最后一个元素
}

NavigableSet

public interface NavigableSet<E> extends SortedSet<E> {//扩展的 SortedSet,具有了搜索匹配元素方法          JDK1.7   java.util
E lower(E e);//返回此 set中小于给定元素的最大元素
E floor(E e);//返回此 set中小于等于给定元素的最大元素
E ceiling(E e);//返回此 set中大于等于给定元素的最小元素
E higher(E e);//返回此 set中大于给定元素的最小元素
E pollFirst();//获取并移除第一个元素
E pollLast();//获取并移除最后一个元素
Iterator<E> iterator();//以升序返回在此set的元素上进行迭代的迭代器
NavigableSet<E> descendingSet();//返回此 set中所包含元素的逆序视图
Iterator<E> descendingIterator();//以降序返回在此 set的元素上进行迭代的迭代器。效果等同于 descendingSet().iterator()。
//返回此 set 的部分视图,其元素范围从 fromElement 到 toElement
NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive);
//返回此 set的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement
NavigableSet<E> headSet(E toElement, boolean inclusive);
//返回此 set的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement
NavigableSet<E> tailSet(E fromElement, boolean inclusive);
//返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。
SortedSet<E> subSet(E fromElement, E toElement);
//返回此 set的部分视图,其元素严格小于 toElement
SortedSet<E> headSet(E toElement);
//返回此 set的部分视图,其元素大于等于 fromElement
SortedSet<E> tailSet(E fromElement);
}

HashSet

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable

阅读HashSet的源码,其实很简单,就是在里面维护了一个 HashMap类型的成员变量,然后抽象出了几个增删改查的方法。需要深入了解的话可以阅读:java容器类2:Map及HashMap深入解读

这里有个疑问,HashMap是存放键值对的,而HashSet是存放一组数据的,为什么可以用HashMap保存set数据?

HashMap中的keySet()函数返回的就是一个 Set类型的数据(不能有重复的key值),所以HashSet将Set数组全部存放在HashMap的keySet中,value值全部用默认的一个Object类型的常量表示。

HashSet中的add()函数可以看出

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

TreeSet


TreeSet的继承关系如下,看上去还挺复杂

正如TreeSet继承自SortSet一样,TreeSet中存储了排序的数组(每个元素值不能有重复的元素)。

同HashSet实现方法相同,里面维护了一个map(NavigableMap类型)类型的成员变量,来保证所有数据是有序的。map里面的keySet字段可以保存TreeSet的所有值。

TreeSet中的方法都是基于NavigableMap的增删改查操作,这里不详细分析。

参考:

http://www.cnblogs.com/NeilZhang/p/8577991.html

java容器类3:set/HastSet/MapSet深入解读的更多相关文章

  1. java容器类4:Queue深入解读

    Collection的其它两大分支:List和Set在前面已近分析过,这篇来分析一下Queue的底层实现. 前三篇关于Java容器类的文章: java容器类1:Collection,List,Arra ...

  2. Java容器类接口的选择

    我们知道Java容器类实际提供了四类接口:Map,List,Set和Queue,如下图所示,每种接口都有不止一个版本的实现,如果在实际编写程序时需要使用某种接口时该如何选择. 从Oracle的Java ...

  3. Java容器类概述

    1.简介 容器是一种在一个单元里处理一组复杂元素的对象.使用集合框架理论上能够减少编程工作量,提高程序的速度和质量,毕竟类库帮我们实现的集合在一定程度上时最优的.在Java中通过java.util为用 ...

  4. java 容器类大集结

    这个世界是程序员的世界,归根到底是数据的世界,要统治这个世界,首先要学会征服数据. 没有最好的,只有最合适的,如何在不同的环境先选择最优的存储的结构呢?且看下文分解: 以下内容部分来自网络,参考: h ...

  5. 【转】java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别

    原文网址:http://www.360doc.com/content/15/0427/22/1709014_466468021.shtml java 容器类使用 Collection,Map,Hash ...

  6. Java容器类List、ArrayList、Vector及map、HashTable、HashMap的区别与用法

    Java容器类List.ArrayList.Vector及map.HashTable.HashMap的区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数 ...

  7. java容器类---概述

    1.容器类关系图 虚线框表示接口. 实线框表示实体类. 粗线框表示最经常使用的实体类. 点线的箭头表示实现了这个接口. 实线箭头表示类能够制造箭头所指的那个类的对象. Java集合工具包位于Java. ...

  8. Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable

    Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable接口,泛型 Collection,List,Se ...

  9. java初学者必看之构造方法详细解读

    java初学者必看之构造方法详细解读 构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法. 格式 public 类名称(参数类型 参数名称){ 方法体 } 注 ...

随机推荐

  1. 初学node.js有感一

    Node.js感悟 一.前言 很久以前就对node.js十分的好奇和感兴趣,因为种种原因没能去深入的认识了解和学习掌握这门技术,最近正好要做一些项目,其中就用到了node.js中的一些东西,所以借着使 ...

  2. cmd命令报4048错误

    解决方法: win10系统:快捷键win+x,找到命令提示符(管理员),打开再下载相应的依赖包. win7/8:打开开始,输入命令提示符,找到管理员权限的命令提示符,打开再下载相应的依赖包. 提示:如 ...

  3. ACdream 1031 Cut

    题意:给定一棵树,删除一些边,让整棵树被分成多个节点数为偶数的联通块,且联通块尽量多. 思路:如果出现连通且节点数为偶数的立即删除这个点与它父节点之间的边,尽量删除即可,因为题目说了保证n为偶数,删了 ...

  4. UVA1600 状态BFS

    刚开是我用了一种很笨的bfs过掉的,后来看到原来还可以三维带状态BFS,觉得是一个不错的思路. d[x][y][k]表示坐标位于(x,y)经过K个障碍到达时的最短路径,当然如果(x,y)处的数字是0就 ...

  5. mybatis 3.x源码深度解析与最佳实践(最完整原创)

    mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...

  6. 转 Caffe学习系列(9):运行caffe自带的两个简单例子

    为了程序的简洁,在caffe中是不带练习数据的,因此需要自己去下载.但在caffe根目录下的data文件夹里,作者已经为我们编写好了下载数据的脚本文件,我们只需要联网,运行这些脚本文件就行了. 注意: ...

  7. js中对一组数组进行求和

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. PCI9054 DMA设置流程

    1.设置方式寄存器:设置DMA通道的传输方式,寄存器DMAMODE0或者DMAMODE1的位9:0-表示块传输,1-表示散/聚传输: 2.设置PCI地址寄存器:设置PCI总线侧的地址空间. 3.设置L ...

  9. mysql常用基础操作语法(十)~~子查询【命令行模式】

    mysql中虽然有连接查询实现多表连接查询,但是连接查询的性能很差,因此便出现了子查询. 1.理论上,子查询可以出现在查询语句的任何位置,但实际应用中多出现在from后和where后.出现在from后 ...

  10. DirectShow使用说明

    1) 安装directX sdk 2)打开安装目录下的dshow.dsw,进行编译 3)在VC++的Tools/Option/Directory的Include和Library中分别加入 C:/DXS ...