Java集合详解--什么是Set_java set-程序员宅基地

技术标签: 排序  comparator  java  set  java积累  

简述


这里写图片描述

Set和List一样,也继承于Collection,是集合的一种。和List不同的是,Set内部实现是基于Map的,所以Set取值时不保证数据和存入的时候顺序一致,并且不允许空值,不允许重复值。

然后我们来看下Set的继承结构

这里写图片描述

可以看出,Set主要有2个实现方式,一个是TreeSet,另一个是HashSet
这个Set的特点,主要由其内部的Map决定的,可以负责人的说一句,Set就是Map的一个马甲

HashSet和TreeSet


就如它的名字一样,HashSet主要由HashMap实现

这里写图片描述

如果调用HashSet的无参构造函数,那么就会使用默认的HashMap,初始化Size为16,扩张系数为0.75

    //简单看下HashMap的几个主要数据执行操作都是间接的调用了内部的HashMap的数据操作
    //比较有意思的是,从add()方法看出,HashSet的值是HashMap的key,
    //HashMap的value是写死的PRESENT
    //所以遍历HashSet的值,也就是遍历HashMap的KeyEntry
    /**
     * Returns an iterator over the elements in this set.  The elements
     * are returned in no particular order.
     *
     * @return an Iterator over the elements in this set
     * @see ConcurrentModificationException
     */
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

    /**
     * Returns the number of elements in this set (its cardinality).
     *
     * @return the number of elements in this set (its cardinality)
     */
    public int size() {
        return map.size();
    }

    /**
     * Returns <tt>true</tt> if this set contains no elements.
     *
     * @return <tt>true</tt> if this set contains no elements
     */
    public boolean isEmpty() {
        return map.isEmpty();
    }

    /**
     * Returns <tt>true</tt> if this set contains the specified element.
     * More formally, returns <tt>true</tt> if and only if this set
     * contains an element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this set is to be tested
     * @return <tt>true</tt> if this set contains the specified element
     */
    public boolean contains(Object o) {
        return map.containsKey(o);
    }

    /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

    /**
     * Removes the specified element from this set if it is present.
     * More formally, removes an element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
     * if this set contains such an element.  Returns <tt>true</tt> if
     * this set contained the element (or equivalently, if this set
     * changed as a result of the call).  (This set will not contain the
     * element once the call returns.)
     *
     * @param o object to be removed from this set, if present
     * @return <tt>true</tt> if the set contained the specified element
     */
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

    /**
     * Removes all of the elements from this set.
     * The set will be empty after this call returns.
     */
    public void clear() {
        map.clear();
    }

TreeSet和HashMap的处理方式相似,这里就不重复展开,区别的地方是,TreeSet内部的是一颗红黑树,至于红黑树的特点,再下一章会详细展开

comparator和comparable


由于Set的实现都基于Map,所以操作都十分简单,所以在这章把Map会提到的comparator和comparable提前分析

直观的翻译我们也可以得出,这2个东西都是和排序有关。

comparator和comparable都是接口。

1.comparable

先来看看comparable

这里写图片描述

Comparable 接口强行对实现它的每个类的对象进行整体排序,Java称这种排序为自然排序,对比于comparator,又称为内部排序

Comparable接口只有一个方法

public int compareTo(T o);

对于需要排序的对象,只要继承这个接口,实现这个compareTo()方法就可以了,(T o)代表传入的数据,需要进行比较的对象。如果位于对象 o 之前,返回负值,如果两个对象在排序中位置相同,则返回 0 ,如果位于对象 o 后面,则返回正值。
在注释中又说到,希望把comparaTo()和equal()联系起来。因为这个2个方法都是对对象进行比较,如果这2个方法对同一个比较对象产生不同的结果,会造成逻辑上的困惑。

举个例子,

class Test{
    int compareFactor;

    //setCompareFactor...getCompareFactor...

    public int compareTo(T o){
    if(o == null){
    //这里是注释上建议这么做的,如果传入一个空值,需要抛出一个异常
        throw new RuntimeException ("test");
    }

    //如果相等,表示处于比较的同一个位置
    if(this.compareFactor == ((Test)o).getCompareFactor()){
        return 0;
    } else if(this.compareFactor > ((Test)o).getCompareFactor()){
        return 1;
    } else {
        return 0;
    }

}

//使用的时候只要调用Collections或者Array的sort()方法就好了
Collections.sort(list);

2.Comparator

相对于Comparable ,comparator又称为外部排序。对于一些已经封装好的对象,我们在尽量不修改已有结构的基础上,通过实现Comparator类来新建一个比较器,然后通过该比较器来对类进行排序。Comparator 接口其实就是一种策略模式的实践

Comparator内部包含了2个方法

int compare(T o1, T o2);

boolean equals(Object obj);

由于所有java对象都继承于Object,所以equals(Object obj)已经被实现了,我们只要实现compare(T o1, T o2)方法就好了。实现的思路和comparable一样,只不过comparable是和自己比较,Comparator是对于两个对象进行比较。

3.异同

Comparable是由对象自己实现的,一旦一个对象封装好了,compare的逻辑也就定了,如果我们需要对同一个对象增加一个字段的排序就比较麻烦,又要修改对象本身。比如淘宝的购买页面,增加一种受欢迎度的排序,就需要修改对象内部compare方法。好处是对外部不可见,调用者无需知道排序逻辑,只要调用排序即可,类似于静态绑定。

而Comparator由外部实现,比较灵活,争对上述问题,只要新增一个Comparator即可。缺点是所有排序逻辑对外部暴露,需要对象外部实现。不过这里的外部仅指对象的外部,也可以由API的开发者封装好所有的Comparator,对调用者隐藏内部逻辑。好处是很灵活,随时可以增加一种排序方法,只要对象内部字段支持,类似动态绑定。

总结


在这一章节中简单介绍了Set的结构,实现原理。Set是Map的一个马甲,主要逻辑都交给Map实现。在下一章中,会详细介绍Map的实现原理。

还介绍了与排序相关的两个接口comparator和comparable

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wz249863091/article/details/52903871

智能推荐

linux关于profile 、bashrc 、.bash_profile、.bashrc的区别_linux profile bashrc-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏11次。linux关于profile 、bashrc 、.bash_profile、.bashrc的区别 - /etc/profile /etc/bashrc ~/.bash_profile ~/.bashrc 作用范围 系统全局所有用户 系统全局所有用户 针对单个用户有效,如/home/user1/.bash_profile 中设定了环境变量,只针对 u_linux profile bashrc

springBoot源码之servlet与reactive_servlet和reactive-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏5次。英语好的可以参考spring的官方文档:https://spring.io/reactiveReactive系统适合低延迟、高吞吐量的工作负载;Reactive Project和Spring结合,可以让开发人员搭建企业级的反应式系统,该系统是响应式的、弹性的、灵活的、消息驱动的。是Spring的reactive栈的非阻塞的基础,比如Spring WebFlux, Spring Data, 和 Spring Cloud Gateway。_servlet和reactive

svn【偷取此锁定】或【破除锁定】解锁SVN被锁定的文件的控制权-程序员宅基地

文章浏览阅读162次。现在很多项目开发都使用SVN作为馆控工具,SVN馆中的文件既可以以文件夹的方式获取,也可以通过eclipse导入。获取文件后,我们可以对某个文件锁定。 如果某个同事锁定了某个文件,而他却找不到是在哪个地方(如工程或文件夹)锁定了该文件,则我们可以通过下面的方式获取该文件的控制权。 偷锁然后再解锁操作SVN时中断锁定,文件的解锁方法1、右健选择svn --&gt;获取锁定:..._svn偷锁

在Protel DXP中建造自己的原理图库-程序员宅基地

文章浏览阅读316次。Protel DXP是Altium公司的桌面板级电路设计系统,它集原理图设计输入、PCB设计绘制、模拟电路仿真、数字电路仿真、VHDL混合输入、FPGA设计、信号完整性分析等诸多功能于一体,是非常优秀的EDA软件.Protel DXP提供了丰富的元器件库,这些元器件库主要是集成库和PCB库.Protel DXP没有单独的原理图库,原理图符号存在于集成库中.即使这样,在使用的过程中,有时也经常遇到..._dxp 原理图生成元件库

Django-自定义过滤器_django自定义过滤器-程序员宅基地

文章浏览阅读2.3k次,点赞3次,收藏5次。文章目录一、使用步骤1.创建文件2.导入注册过滤器的Library 实例一、使用步骤1.创建文件创建templatetags(必须是这个名字)文件夹在你的应用下创建templatetags文件夹如果文件夹名字不是templatetags可能会出现以下错误在templatetags文件夹下创建my_tags.py(文件名可自定义)2.导入注册过滤器的Library 实例代码如下from django import template# 下面代码会直接使用register_django自定义过滤器

17. 【C语言】有一个学生结构体,其数据成员有: 学号, 姓名, 3 门课程分数。从键盘上输入 5 个学生 的信息,按要求输出(5_task)_用结构体输入5个学生信息在输出-程序员宅基地

文章浏览阅读1.5w次,点赞20次,收藏97次。问题描述:有一个学生结构体,其数据成员有: 学号, 姓名, 3 门课程分数。从键盘上输入 5 个学生的信息,按如下要求输出:(1) 按照学号递增输出全部学生信息,每个学生的信息一行。(格式: 学号 姓名 分数1 分数 2 分数 3 总分)(2) 输出每门课程最高分的学生的信息(3) 输出每门课程的平均分(4) 按照总分输出学生排名算法思想:(1)第1问要求按学号递增输出信息,在不确定..._用结构体输入5个学生信息在输出

随便推点

BeeGFS-Mon对接Grafana-程序员宅基地

文章浏览阅读708次。从Version 7开始,BeeGFS引入了 beegfs-mon 守护进程,该进程从系统收集统计信息,然后使用时间序列数据库(InfluxDB)向用户提供。为了可视化数据,beegfs-mon 提供了预定义的Grafana面板,用户可以直接使用这些面板,也可以使用任何他们喜欢的工具。安装beegfs-mon服务以及Grafana面板都包含在 beegfs-mon安装包中。该安装包在Be..._beegfs-mon对接grafana

《MySQL实战45讲》——学习笔记23 “binlog&redolog 的写入机制/组提交机制“_mysql组提交-程序员宅基地

文章浏览阅读929次。本篇主要介绍数据的可靠性有关的知识,包括binlog的写入机制和redolog 的写入机制;_mysql组提交

JAVA编程思想--多态_多态编程思想-程序员宅基地

文章浏览阅读220次。多态:消除类型之间的耦合关系(分离做什么和怎么做),基于继承的向上转型功能,允许同一种类型同一行为有不同的表现。动态绑定使得多态中的基类对象可以正确执行相应的导出类对象方法。多态使得扩展新类型和扩展基类不会对已有代码(调用基类方法的代码)产生影响。它可以让程序员“将改变的事物与不变的事物分离开”。_多态编程思想

操作系统研究的“奥斯卡” 首次独归亚州!解读SOSP 2023最佳论文 TreeSLS:基于单级存储的全系统持久微内核-程序员宅基地

文章浏览阅读903次,点赞21次,收藏17次。SOSP’23最佳论文TreeSLS是一种基于持久内存(NVM)实现单级存储(single-level store, SLS)、支持全系统持久性的微内核。TreeSLS是上海交大陈海波教授团队的最新佳作,是自1967年首届SOSP召开以来首篇由亚洲研究人员独立获得的最佳论文。本文将带您深入了解TreeSLS的研究背景、关键技术、评估结果和研究贡献,以及作者在论文问题定位方面的技巧。

iOS7下获取内付费的receipt及receipt样例_苹果 receipt 怎么来的-程序员宅基地

文章浏览阅读5.6k次。iOS7下获取内付费的receipt苹果receipt样例_苹果 receipt 怎么来的

tomcat常出现的几种错误总结_状态报告 消息 请求的资源[/denglu.html]不可用 描述 源服务器未能找到目标资源的-程序员宅基地

文章浏览阅读3.5k次。tomcat常见的问题总结HTTP状态 404 - 未找到类型 状态报告消息 请求的资源[/]不可用描述 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示。Apache Tomcat/9.0.381.tomcat环境变量的配置(官方原稿)(3.1) Set CATALINA_HOME (required) and CATALINA_BASE (optional)The CATALINA_HOME environment variable should be set t_状态报告 消息 请求的资源[/denglu.html]不可用 描述 源服务器未能找到目标资源的

推荐文章

热门文章

相关标签