Java基础 - 07 Set之Set,AbstractSet

news2024/9/9 5:24:25

上边几篇,我们对java的List集合进行相关介绍,了解了关于List集合下的相关实现类的方法或者接口。

自本篇开始,将围绕java的Set进行介绍,也是对我java知识的巩固吧,处理业务越多,发现自己对基础知识的薄弱,于是又回头继续学习,没办法,学习就是这样,忘记又学,学了又忘,听他们说,把东西理解了,并掺杂自己的想法就不会忘记了,我也不知道是不是真的,算了废话不多说了,开始介绍Set集合了;

Set集合

在这里插入图片描述

Set作为Java中的一个接口,它继承自Collection接口,用于存储不重复的元素, Set不保证元素的顺序,且不允许包含重复元素。

Set的特点包括:

  • 不允许重复的元素: set中的元素是唯一的,如果试图向Set中添加重复的元素,则添加操作将被忽略。

  • 具备无序性: Set中的元素没有固定的顺序,不同的实现类可能以不同的方式存储和遍历元素。

  • 具备高效性: Set提供了高效的元素查找和插入操作,通常使用哈希表或者树等数据结构来实现。

在这里插入图片描述

Set定义的常用的方法,例如

  • 添加元素:add(element):向Set中添加指定元素。
  • 删除元素:remove(element):从Set中移除指定元素。
  • 判断是否包含元素:contains(element):判断Set中是否包含指定元素。
  • 获取元素个数:size():返回Set中元素的个数。
  • 清空Set:clear():移除Set中的所有元素。
  • 遍历Set:可以使用迭代器或增强for循环来遍历Set中的元素。
public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        // 添加元素
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("apple"); // 重复元素,将被忽略
        // 判断是否包含元素
        System.out.println(set.contains("apple")); // 输出:true
        System.out.println(set.contains("grape")); // 输出:false
        // 获取元素个数
        System.out.println(set.size()); // 输出:3
        // 遍历Set
        for (String element : set) {
            System.out.println(element);
        }
        // 删除元素
        set.remove("banana");
        // 清空Set
        set.clear();
    }

注意一下,Set重写了equals和hashCode方法。

用途:

  • 去重:当需要从一组数据中去除重复元素时,可以使用Set来存储数据,因为Set会自动去除重复元素。

  • 查找:由于Set内部使用哈希表或树等数据结构实现,查找操作的时间复杂度为O(1)或O(log n),因此在需要快速查找元素的场景下,Set是一个很好的选择。

  • 数学集合运算:Set提供了一些集合运算的方法,如交集、并集、差集等,可以方便地进行集合操作。

Set的优点:

  • 去重功能:Set保证元素的唯一性,可以自动去除重复元素,简化了去重操作。
  • 高效的查找和插入操作:Set的底层实现通常使用哈希表或树等数据结构,使得查找和插入操作具有高效性。
  • 提供了集合运算方法:Set提供了一些集合运算的方法,方便进行集合操作。

Set的缺点:

  • 无序性:Set中的元素没有固定的顺序,无法按照特定的顺序进行访问和遍历。

  • 不支持索引访问:Set接口不提供索引访问元素的方法,无法通过索引直接访问元素,需要使用迭代器或其他方式进行遍历。

  • 内存占用较大:由于Set需要保证元素的唯一性,可能需要额外的内存空间来存储哈希值或比较元素,因此在存储大量数据时,可能会占用较多的内存。

举例说明

交集(Intersection):获取两个Set中共同存在的元素。
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);

System.out.println(intersection); // 输出:[4, 5]

创建了两个Set,分别包含一些整数元素。然后,我们创建一个新的Set ntersection,并将其初始化为set1的副本。接下来,我们使用retainAll()方法将intersectionset2取交集,最终得到的结果是[4, 5],即两个Set中共同存在的元素。

并集(Union):获取两个Set中所有的不重复元素。
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

Set<Integer> union = new HashSet<>(set1);
union.addAll(set2);

System.out.println(union); // 输出:[1, 2, 3, 4, 5, 6, 7, 8]

我们创建了两个Set,分别包含一些整数元素。然后,我们创建一个新的Set union,并将其初始化为set1的副本。接下来,我们使用addAll()方法将set2中的元素添加到union中,最终得到的结果是[1, 2, 3, 4, 5, 6, 7, 8],即两个Set中所有的不重复元素。

差集(Difference):获取在第一个Set中存在但在第二个Set中不存在的元素。
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

Set<Integer> difference = new HashSet<>(set1);
difference.removeAll(set2);

System.out.println(difference); // 输出:[1, 2, 3]

我们创建了两个Set,分别包含一些整数元素。然后,我们创建一个新的Set difference,并将其初始化为set1的副本。接下来,我们使用removeAll()方法将set2中的元素从difference中移除,最终得到的结果是[1, 2, 3],即在第一个Set中存在但在第二个Set中不存在的元素。

在这里插入图片描述

AbstractSet< E >

AbstractSet是一个抽象类,它实现了Set接口的大部分方法,提供了一些通用的实现,使得编写自定义的Set实现类变得更加简单。
在这里插入图片描述

在这里插入图片描述

相关方法

add(E e):向集合中添加指定的元素。默认实现会抛出UnsupportedOperationException异常,因此,具体的子类需要重写该方法来实现添加元素的逻辑。

addAll(Collection<? extends E> c):将指定集合中的所有元素添加到当前集合中。默认实现会遍历指定集合,并逐个调用add()方法来添加元素。

clear():从集合中移除所有的元素。默认实现会遍历集合,并逐个调用remove()方法来移除元素。

contains(Object o):判断集合是否包含指定的元素。默认实现会遍历集合,并逐个调用equals()方法来比较元素。

containsAll(Collection<?> c):判断集合是否包含指定集合中的所有元素。默认实现会遍历指定集合,并逐个调用contains()方法来判断元素是否存在。

equals(Object o):判断当前集合是否与指定对象相等。默认实现会比较集合的大小和元素是否相同。

hashCode():返回当前集合的哈希码值。默认实现会遍历集合,并累加每个元素的哈希码值。

isEmpty():判断集合是否为空。默认实现会判断集合的大小是否为0。

iterator():返回一个用于遍历集合的迭代器。默认实现会返回AbstractSet的内部类Iterator的实例。

remove(Object o):从集合中移除指定的元素。默认实现会遍历集合,并逐个调用equals()方法来比较元素。

removeAll(Collection<?> c):从集合中移除指定集合中的所有元素。默认实现会遍历指定集合,并逐个调用remove()方法来移除元素。

retainAll(Collection<?> c):仅保留集合中与指定集合中相同的元素,移除其他元素。默认实现会遍历集合,并逐个调用contains()方法来判断元素是否存在。

size():返回集合中的元素个数。默认实现会遍历集合并计数。

toArray():将集合转换为数组。默认实现会创建一个新的数组,并将集合中的元素复制到数组中。

案例

AbstractSet在Java中的作用是为自定义的Set实现类提供了一些通用的方法实现,简化了编写Set实现类的过程。通过继承AbstractSet,我们只需要关注实现自定义的Set特有的方法,而无需重复编写已经在AbstractSet中实现的方法。

public class MySet<E> extends AbstractSet<E> {
    private Object[] elements;
    private int size;

    public MySet() {
        elements = new Object[10];
        size = 0;
    }

    @Override
    public boolean add(E e) {
        if (contains(e)) {
            return false;
        }
        if (size >= elements.length) {
            // 扩容数组
            Object[] newElements = new Object[elements.length * 2];
            System.arraycopy(elements, 0, newElements, 0, size);
            elements = newElements;
        }
        elements[size++] = e;
        return true;
    }

    @Override
    public Iterator<E> iterator() {
        return new MySetIterator();
    }

    @Override
    public int size() {
        return size;
    }

    private class MySetIterator implements Iterator<E> {
        private int cursor;

        @Override
        public boolean hasNext() {
            return cursor < size;
        }

        @Override
        public E next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return (E) elements[cursor++];
        }
    }
}

我们创建了一个名为MySet的自定义Set实现类,它继承自AbstractSet。我们只需要实现add()、iterator()和size()这三个抽象方法,而其他方法如contains()、remove()等已经在AbstractSet中实现了。

在MySet中,我们使用一个数组elements来存储集合中的元素,size表示集合的大小。在add()方法中,我们首先判断元素是否已经存在于集合中,如果存在则返回false,否则将元素添加到数组中。如果数组已满,则扩容数组。在iterator()方法中,我们返回一个内部类MySetIterator的实例,用于遍历集合中的元素。在size()方法中,我们直接返回集合的大小。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构小项目----通讯录的实现(这里用链表实现) 超详细~~~~૮(˶ᵔ ᵕ ᵔ˶)ა

目录 Contact.h说明&#xff1a; 结构体与头文件的包含&#xff1a; ​编辑 函数在头文件的声明与定义&#xff1a; Contact.c中各个函数的实现&#xff1a; 1.检查链表中的数据是否满了&#xff0c;满了就扩容 2.链表的尾插 3.链表的删除 4.查找名字是否匹配 5.初始化通讯…

Vagrant安装Oracle Data Guard环境示例

在Windows 11下&#xff0c;通过Vagrant安装标准的Data Guard环境&#xff08;默认为non-CDB模式&#xff09;&#xff0c;耗时约26分钟&#xff0c;共生成2台虚机。以下为安装日志&#xff1a; ...host2: Welcome to DGMGRL, type "help" for information.host2: C…

b+树的理解

二叉树&#xff1a; 每个节点支持两个分支的树结构&#xff0c;相比于单向链表&#xff0c;多了一个分支。 二叉查找树&#xff1a; 在二叉树的基础上增加了一个规则&#xff0c;左子树的所有节点都小于它的根节点&#xff0c;右子树的所有节点都大于他的根节点。 二叉查找树…

Beego之Beego快速入门

1、beego快速入门 1.1 新建项目 新建一个项目&#xff1a; [rootzsx src]# bee new quickstart 2023/02/19 15:55:50.370 [D] init global config instance failed. If you do not use this, just ignore it. open conf/app.conf: no such file or directory 2023/02/19 1…

易优demo网站测试结果

易优demo网站测试结果-06 1、信息收集 网站账号&#xff1a;admin 密码&#xff1a;Aa123456 2、存在的漏洞 2.1 后台弱口令漏洞 http://eyoucms-s347fqn.gxalabs.com/login.php?sAdmin/login网站账号&#xff1a;admin 密码&#xff1a;Aa123456 成功登陆 2.2 代码远程…

递归、搜索与回溯算法(专题二:深搜)

往期文章&#xff08;希望小伙伴们在看这篇文章之前&#xff0c;看一下往期文章&#xff09; &#xff08;1&#xff09;递归、搜索与回溯算法&#xff08;专题零&#xff1a;解释回溯算法中涉及到的名词&#xff09;【回溯算法入门必看】-CSDN博客 &#xff08;2&#xff09…

linux基础学习(5):yum

yum是为了解决rpm包安装依赖性而产生的一种安装工具 1.yum源 1.1配置文件位置 yum源的配置文件在/etc/yum.repos.d/中 *Base源是网络yum源&#xff0c;也就是需要联网才能使用的yum源。默认情况下&#xff0c;系统会使用Base源 *Media源是光盘yum源&#xff0c;是本地yum源…

openjdk源码了解

openjdk给出debug配置选项&#xff0c;common/autoconf/jdk-options.m4 AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL], [################################################################################# Set the debug level# release: no debug information, all opti…

Jenkins实现CICD(1)_Windows10 安装Jenkins

文章目录 一、打开Jenkins官网&#xff0c;下载安装包二、安装Jenkins三、JAVA环境_JDK17下载安装&#xff08;Windows版&#xff09;四、将jdk-17添加到系统环境变量五、jenkins关联jdk-17六、安装常用插件(例如&#xff1a;git、gitlab、钉钉) 一、打开Jenkins官网&#xff0…

PDshell16逆向PostgreSQL 工程显示字段comment备注

现状&#xff1a;当刚逆向成功的表结构是没有原来表结构中的&#xff0c;comment备注如下 然后pd逆向工程的sql已经返回了这个备注的含义 解决方案&#xff1a; 1、设置显示注释列 tools——Display Preferences…如下 勾选-按照下面得方式勾选这三个 复制这里的VBS脚本&a…

Python数据分析案例37——基于分位数神经网络(QRNN)的汇率预测

案例背景 我导师的研究方向是少有的做"分位数回归"方向&#xff0c;作为研究机器学习深度学习方向的我自然就继承了这个特色&#xff0c;改进出了很多特殊结合方法&#xff0c;我会结合各种机器学习方法和各种分位数回归的方法。 之前写过分位数随机森林&#xff0…

哈希表 -- 刷题(查找算法)

目录 &#x1f4bb;哈希 -- 知识点 &#x1f40d;刷题 &#x1f33c;1&#xff0c;雪花 AC -- vector AC -- 链式前向星 &#x1f33c;2&#xff0c;公式 &#x1f4bb;哈希 -- 知识点 线性表 和 树表&#xff0c;通过比较关键字进行查找 而 散列表&#xff0c;基于…

【MATLAB源码-第119期】基于matlab的GMSK系统1bit差分解调误码率曲线仿真,输出各个节点的波形以及功率谱。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 GMSK&#xff08;高斯最小频移键控&#xff09;是一种数字调制技术&#xff0c;广泛应用于移动通信&#xff0c;例如GSM网络。它是一种连续相位调频制式&#xff0c;通过改变载波的相位来传输数据。GMSK的关键特点是其频谱的…

【接上篇】二、Flask学习之CSS(下篇)

上篇&#xff1a;二、Flask学习之CSS 3.8hover hover是用来美化鼠标悬停的效果的&#xff0c;当鼠标停放在某个区域&#xff0c;就会执行对应的hover操作。可以操作本标签的内容&#xff0c;也可以操作本标签下某一个标签的内容 3.9after <!DOCTYPE html> <html l…

Navicat平替工具,一款免费开源的通用数据库工具

前言 前段时间有小伙伴在群里提问说&#xff1a;因为公司不允许使用破解版的Navicat&#xff0c;有好用的Navicat平替工具推荐吗&#xff1f;今天分享一款免费开源的通用数据库工具&#xff1a;DBeaver。 DBeaver工具介绍 DBeaver是一款免费的跨平台数据库工具&#xff0c;适…

灵活扩展:深入理解MyBatis插件机制

第1章&#xff1a;MyBatis插件的重要性 大家好&#xff0c;我是小黑&#xff0c;咱们今天要聊的是MyBatis插件&#xff0c;MyBatis&#xff0c;大家都不陌生&#xff0c;它是一个ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;让咱们在操作数据库时能更加优雅。但今…

“深入理解 Docker 和 Nacos 的单个部署与集成部署“

目录 引言&#xff1a;Docker Nacos 单个部署1.1 什么是 Docker&#xff1f;Docker 的概念和工作原理Docker 为什么受到广泛应用和认可 1.2 什么是 Nacos&#xff1f;Nacos 的核心功能和特点Nacos 在微服务架构中的作用 1.3 Docker 单个部署 Nacos Docker Nacos 集成部署总结&a…

sfml使用opengl着色器实现2d水面波浪

SFML中使用GLSL着色器来绘制水波。 效果 代码 #include <SFML/Graphics.hpp> #include <iostream>int main() {const int WIDTH = 800;

用C语言实现简单的三子棋游戏

目录 1 -> 模块简介 2 -> test.c 3 -> game.c 4 -> game.h 1 -> 模块简介 test.c:测试游戏逻辑 game.c: 函数的实现 game.h:函数的声明 2 -> test.c #define _CRT_SECURE_NO_WARNINGS 1#include "game.h";void menu() {printf("****…

大模型学习与实践笔记(七)

一、环境配置 1.平台&#xff1a; Ubuntu Anaconda CUDA/CUDNN 8GB nvidia显卡 2.安装 # 构建虚拟环境 conda create --name xtuner0.1.9 python3.10 -y # 拉取 0.1.9 的版本源码 git clone -b v0.1.9 https://github.com/InternLM/xtuner# 从源码安装 XTuner pip insta…