Java高级架构师-Java集合 HashSet的原理及常用方法

SpringMVC面试题:什么是Servlet? 一、什么是servlet? servlet是一个Java编写的程序,此程序是基于http协议的,在服务器端(如Tomcat)运行的,是按照servlet规范编写的一个Java类。 客户端发送请求至服务器端,服务器端将请求发送至servlet,servlet生成响应内容并将其传给服务器 即,我们在浏览器点击链接和按钮产生的消息不是发送给servlet的,而是发送给web容器(如Tomcat、jet... 阅读详情

目录

  • 一. HashSet概述
  • 二. HashSet构造
  • 三. add方法
  • 四. remove方法
  • 五. 遍历
  • 六. 合计合计
  • 先看一下LinkedHashSet
  • 在看一下TreeSet
  • 七. 总结

一. HashSet概述

HashSet是Java集合Set的一个实现类,Set是一个接口,其实现类除HashSet之外,还有TreeSet,并继承了Collection,HashSet集合很常用,同时也是程序员面试时经常会被问到的知识点,下面是结构图

 

 

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

二. HashSet构造

HashSet有几个重载的构造方法,我们来看一下

private transient HashMap<E,Object> map;
//默认构造器
public HashSet() {
 map = new HashMap<>();
}
//将传入的集合添加到HashSet的构造器
public HashSet(Collection<? extends E> c) {
 map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
 addAll(c);
}
//明确初始容量和装载因子的构造器
public HashSet(int initialCapacity, float loadFactor) {
 map = new HashMap<>(initialCapacity, loadFactor);
}
//仅明确初始容量的构造器(装载因子默认0.75)
public HashSet(int initialCapacity) {
 map = new HashMap<>(initialCapacity);
}

通过上面的源码,我们发现了HashSet就TM是一个皮包公司,它就对外接活儿,活儿接到了就直接扔给HashMap处理了。因为底层是通过HashMap实现的,这里简单提一下:

HashMap的数据存储是通过数组+链表/红黑树实现的,存储大概流程是通过hash函数计算在数组中存储的位置,如果该位置已经有值了,判断key是否相同,相同则覆盖,不相同则放到元素对应的链表中,如果链表长度大于8,就转化为红黑树,如果容量不够,则需扩容(注:这只是大致流程)。

如果对HashMap原理不太清楚的话,可以先去了解一下

HashMap原理(一) 概念和底层架构

HashMap原理(二) 扩容机制及存取原理

三. add方法

HashSet的add方法时通过HashMap的put方法实现的,不过HashMap是key-value键值对,而HashSet是集合,那么是怎么存储的呢,我们看一下源码

private static final Object PRESENT = new Object();
public boolean add(E e) {
 return map.put(e, PRESENT)==null;
}

看源码我们知道,HashSet添加的元素是存放在HashMap的key位置上,而value取了默认常量PRESENT,是一个空对象,至于map的put方法,大家可以看HashMap原理(二) 扩容机制及存取原理。

 

 

四. remove方法

HashSet的remove方法通过HashMap的remove方法来实现

//HashSet的remove方法
public boolean remove(Object o) {
 return map.remove(o)==PRESENT;
}
//map的remove方法
public V remove(Object key) {
 Node<K,V> e;
 //通过hash(key)找到元素在数组中的位置,再调用removeNode方法删除
 return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value;
}
/**
 * 
 */
final Node<K,V> removeNode(int hash, Object key, Object value,
 boolean matchValue, boolean movable) {
 Node<K,V>[] tab; Node<K,V> p; int n, index;
 //步骤1.需要先找到key所对应Node的准确位置,首先通过(n - 1) & hash找到数组对应位置上的第一个node
 if ((tab = table) != null && (n = tab.length) > 0 &&
 (p = tab[index = (n - 1) & hash]) != null) {
 Node<K,V> node = null, e; K k; V v;
 //1.1 如果这个node刚好key值相同,运气好,找到了
 if (p.hash == hash &&
 ((k = p.key) == key || (key != null && key.equals(k))))
 node = p;
 /**
 * 1.2 运气不好,在数组中找到的Node虽然hash相同了,但key值不同,很明显不对, 我们需要遍历继续
 * 往下找;
 */
 else if ((e = p.next) != null) {
 //1.2.1 如果是TreeNode类型,说明HashMap当前是通过数组+红黑树来实现存储的,遍历红黑树找到对应node
 if (p instanceof TreeNode)
 node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
 else {
 //1.2.2 如果是链表,遍历链表找到对应node
 do {
 if (e.hash == hash &&
 ((k = e.key) == key ||
 (key != null && key.equals(k)))) {
 node = e;
 break;
 }
 p = e;
 } while ((e = e.next) != null);
 }
 }
 //通过前面的步骤1找到了对应的Node,现在我们就需要删除它了
 if (node != null && (!matchValue || (v = node.value) == value ||
 (value != null && value.equals(v)))) {
 /**
 * 如果是TreeNode类型,删除方法是通过红黑树节点删除实现的,具体可以参考【TreeMap原理实现
 * 及常用方法】
 */
 if (node instanceof TreeNode)
 ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
 /** 
 * 如果是链表的情况,当找到的节点就是数组hash位置的第一个元素,那么该元素删除后,直接将数组
 * 第一个位置的引用指向链表的下一个即可
 */
 else if (node == p)
 tab[index] = node.next;
 /**
 * 如果找到的本来就是链表上的节点,也简单,将待删除节点的上一个节点的next指向待删除节点的
 * next,隔离开待删除节点即可
 */
 else
 p.next = node.next;
 ++modCount;
 --size;
 //删除后可能存在存储结构的调整,可参考【LinkedHashMap如何保证顺序性】中remove方法
 afterNodeRemoval(node);
 return node;
 }
 }
 return null;
}

removeTreeNode方法具体实现可参考 TreeMap原理实现及常用方法

afterNodeRemoval方法具体实现可参考LinkedHashMap如何保证顺序性

五. 遍历

HashSet作为集合,有多种遍历方法,如普通for循环,增强for循环,迭代器,我们通过迭代器遍历来看一下

public static void main(String[] args) {
 HashSet<String> setString = new HashSet<> ();
 setString.add("星期一");
 setString.add("星期二");
 setString.add("星期三");
 setString.add("星期四");
 setString.add("星期五");
 Iterator it = setString.iterator();
 while (it.hasNext()) {
 System.out.println(it.next());
 }
}

打印出来的结果如何呢?

星期二
星期三
星期四
星期五
星期一

意料之中吧,HashSet是通过HashMap来实现的,HashMap通过hash(key)来确定存储的位置,是不具备存储顺序性的,因此HashSet遍历出的元素也并非按照插入的顺序。

六. 合计合计

按照我前面的规划,应该每一块主要的内容都单独写一下,如集合ArrayList,LinkedList,HashMap,TreeMap等。不过我在写这篇关于HashSet的文章时,发现有前面对HashMap的讲解后,确实简单,HashSet就是一个皮包公司,在HashMap外面加了一个壳,那么LinkedHashSet是否就是在LinkedHashMap外面加了一个壳呢,而TreeSet是否是在TreeMap外面加了一个壳?我们来验证一下

先看一下LinkedHashSet

最开始的结构图已经提到了LinkedHashSet是HashSet的子类,我们来看源码

public class LinkedHashSet<E>
 extends HashSet<E>
 implements Set<E>, 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);
 }
 public Spliterator<E> spliterator() {
 return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
 }
}

上面就是LinkedHashSet的所有代码了,是不是感觉智商被否定了,这基本上没啥东西嘛,构造器还全部调用父类的,下面就是其父类HashSet的对此的构造方法

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
 map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

大家也看出来,和我们的猜测一样,没有深究下去的必要了。如果有兴趣可以看看LinkedHashMap如何保证顺序性

在看一下TreeSet

public class TreeSet<E> extends AbstractSet<E>
 implements NavigableSet<E>, Cloneable, java.io.Serializable
{
 public TreeSet() {
 this(new TreeMap<E,Object>());
 }
 public TreeSet(Comparator<? super E> comparator) {
 this(new TreeMap<>(comparator));
 }
 public TreeSet(Collection<? extends E> c) {
 this();
 addAll(c);
 }
 public TreeSet(SortedSet<E> s) {
 this(s.comparator());
 addAll(s);
 }
}

确实如我们所猜测,TreeSet也完全依赖于TreeMap来实现,如果有兴趣可以看看TreeMap原理实现及常用方法

七. 总结

本文主要介绍了HashSet的原理以及主要方法,同时简单介绍了LinkedHashSet和TreeSet,若有不对之处,请批评指正,望共同进步,谢谢!

 

Q Q交流群: 点击 有任何问题可以加群交流   

Java最新一线架构技术讲解请:点击 内容实用 讲解简单易懂

BitLocker磁盘锁定解决方法 摘要:本文介绍了BitLocker加密磁盘被锁的两种情况及解决方法。对于系统盘锁定,建议在微软账户中查找48位恢复密钥;数据盘锁定可尝试密码或恢复密钥解锁。若密钥丢失,可通过IT支持或数据恢复服务尝试解决。预防措施包括妥善备份密钥到微软账户和离线位置,避免随意更改系统硬件配置。BitLocker安全性高,恢复密钥是解锁关键,提醒用户务必做好备份以防数据丢失。(148字) 阅读详情

相关推荐

人形机器人人机交互解决方案(2026完整版)

《人形机器人人机交互解决方案(2026完整版)》摘要 本项目针对2026年人形机器人产业爆发式增长需求,提出了一套完整的人机交互解决方案。方案包含十大核心模块(语音识别、情感识别、手势识别等),采用五层架构设计,实现多模态融合交互,响应时间≤32ms,准确率≥99%。覆盖制造业巡检、家庭服务等10大场景,适配20+主流机型。项目总投资4.1亿元,预期年营收8.2亿元,将申请专利120项,培养专业人才300人。通过技术创新解决当前交互体验生硬、安全可控性不足等痛点,助力我国人形机器人产业实现从"跟跑

随读手记 776

分析Collection(四)了解HashSet 构造

HashSet 大家应该都知道,Set这个接口下的对象是不能有重复的,为什么不能有重复呢??今天咱就深入扒一下。而且Set也是没有顺序的。 今天我们通过看它的源代码来深入分析一下 本文章不敢和隔壁的大佬相比,只能尽力写的让各位看官看明白,能够了解到HashSet的结构 听别人说,IDEA可以更容易的看到JDK的源代码,不像Eclipse那样,那么麻烦,而且前两天考试的时候规定用IDEA来敲代码,正好今天拿来试试,虽然用过一段时间IDEA,但是感觉还是Eclipse用的熟悉,废话说完了,开始进入正题 开始

Fanx繁星 762

传输线末端短路、开路、加电感的反射系数

时,频率变化约300MHz, 出现这种偏差是因为我们的计算中将电磁波传播速率默认为。时,频率变化约300MHz, 出现这种偏差是因为我们的计算中将电磁波传播速率默认为。下图为用网络分析仪实测一长度为30cm的传输线末端加一0.6uH的线圈的反射系数。下图为用网络分析仪实测一末端短路的长度为30cm的传输线的反射系数。下图为用网络分析仪实测一末端开路的长度为30cm的传输线的反射系数。末端加电感相当于在传输线末端延长了一段后末端短路,使得相位下降速率。幅度为0dB, 相位由。幅度为0dB, 相位由。

johnboat的专栏 1873

Java集合----HashSet的实现原理

1. HashSet概述      HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。 2. HashSet的实现      如果不等,则添加到该数组索引对应

ymeng_bupt的专栏 2万+

[Adaptive Autosar]深入理解--Time Synchronization

目录 1.TS典型应用场景 2.CP和AP时间同步对比 3.时间同步基础知识 4.TBR部分参数说明 5. TS功能说明 5.1 基本说明 5.2 时间纠正计算说明 5.3 时间验证 Time Synchronization 时间同步,后面简称TS 1.TS典型应用场景 时间同步,典型应用就是在自动驾驶领域,自动驾驶领域涉及到各个传感器的数据采集,如IMU采集当前车身姿态和运动信息,毫米波雷达-超声波雷达-环视摄像头-前视摄像头...等等传感器捕获的数据,在算法中需要精确知道每个数.

AgingMoon的博客 3997

西门子【Automation Framework V1.2】AF架构:从软件栈到高效自动化项目的构建蓝图

本文深入解析西门子Automation Framework V1.2 (AF架构) 的核心价值与实施蓝图。该框架通过定义标准化的软件栈(如TIA Portal V19、STEP7、WinCC Unified)和严格的安装配置流程,将自动化项目开发从依赖个人经验的“手工作坊”模式,转变为高效、可复制的工业化模式。遵循此架构,工程师能快速构建稳定可靠的项目基础,规避环境冲突,从而专注于核心工艺与逻辑设计,大幅提升团队协作与项目交付效率。

weixin_29230059的博客 428

HashSet原来这么简单

HashSet学习记录 0、简介 ​ 本篇主要记录下HashSet的源码学习记录,是随机看到的,随手记录下。大家都知道HashMap是一种存储键值对的数据结构,HashSet从名字可以看出来其主要是一个集合,通过数学上集合的概念可以知道集合存放非是没有重复数据的集。HashSet底层实现是通过组合了一个HashMap实现的,通过借助HashMap中key不能重复的特性实现HashSet想要的功能...

fh667788123的博客 572

【Python计量】linearmodels面板数据回归(一)

我们以伍德里奇《计量经济学导论现代方法》的”第14章高级面板数据方法“的案例14.1为例,使用jtrain中的数据来进行固定效应估计。

mfsdmlove的博客 9277

JAVA集合Set之HashSet详解

HashSet这个类实现了Set集合,实际为一个HashMap的实例。并且HashSet提供了三个构造函数

zhaojie181711的博客 17万+

130、NPU的仿真测试:使用Gem5进行全系统仿真

这篇文章摘要(149字): 本文分享了使用Gem5全系统仿真器验证NPU设计的实践经验。作者通过搭建自定义NPU模型并集成到Gem5系统中,实现了CPU-NPU-内存协同仿真。关键点包括:1) 使用SimObject机制构建可配置的NPU模型;2) 合理配置IO和内存总线避免访问冲突;3) 开发Linux驱动实现CPU与NPU通信;4) 利用Gem5调试功能监控内部状态。相比RTL仿真和FPGA验证,该方法能快速验证微架构设计并定位系统级问题,有效减少了流片风险。文章特别强调了时钟域配置、总线仲裁、对齐访问

m0_50546716的博客 122

1. SAP Business Application Studio 里创建一个基于 CAP 模型的最简单的 OData 服务

本文基于 SAP Cloud Application Programming 编程模型的 OData 服务开发教程的第一步,简述了 SAP Business Technology Platform 里 Business Application Studio 开发工具的打开方式,创建 Dev Space 以及 CAP 项目的创建步骤,以及如何通过 schema.cds 和 service.cds 分别创建 OData 模型和 OData 服务,最后通过 ports preview 打开 OData 服务预览页

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1798

【数据结构】HashSet原理及实现学习总结

在上一篇博文(HashMap原理及实现学习总结)详细总结了HashMap的实现过程,对于HashSet而言,它是基于HashMap来实现的,底层采用HashMap来保存元素。所以如果对HashMap比较熟悉,那么HashSet的原理应该很好理解!一.HsahSet概述HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变

简约人生的博客 1万+

Transformer实战(32)——Transformer模型压缩

在本节中,我们学习了如何在硬件资源受限的情况下减轻运行大模型的负担。我们介绍了如何通过蒸馏、剪枝和量化从训练好的模型中提取高效模型。预训练轻量级的通用语言模型(如 DistilBERT) 可以在各种任务上进行微调,并表现出与非蒸馏模型相当的性能。随着数据量的不断增加,我们希望模型能够更快地运行,在这方面,高效 Transformer 起着至关重要的作用。

盼小辉丶的博客 2554

ajax的url在java中对应方法怎么找到_Java高级架构师-Java集合 HashSet的原理及常用方法...

目录一. HashSet概述二. HashSet构造三. add方法四. remove方法五. 遍历六. 合计合计先看一下LinkedHashSet在看一下TreeSet七. 总结一. HashSet概述HashSet是Java集合Set的一个实现类,Set是一个接口,其实现类除HashSet之外,还有TreeSet,并继承了Collection,HashSet集合很常用,同时也是程序员面试时经常...

weixin_32515445的博客 130

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

java 接口_Java高级架构师-JAVA基础之Set接口

欢迎关注头条号:Java小野猫个人理解:Set接口是Collection接口的子类,其继承了所有方法,HashSet集合则实现了Set接口,其内部存储数据时依靠哈希表,一个类似数组和链表的结合体。设置空集合时,存在默认的容量和加载因子,再用HashSet对象调用add方法时,其实是先比较其Hash值,若是没有的话,则直接添加到集合中,若有的话,则再equals下比较其内容(因为有可能内容不一样,但...

weixin_39843847的博客 64

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Java架构师大厂面试致命十连问,你接得住吗?

很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!4、Bean的销毁1、使用配置文件中的 destory-method 属性。

2401_84010107的博客 1089

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java面试3天冲刺攻略:高频考点+实战刷题+避坑指南

Java作为企业级应用开发的核心语言,其面试准备需要系统性的知识体系构建。从Java虚拟机内存模型到并发编程原理,理解底层机制是应对技术考察的基础。HashMap作为集合框架的关键组件,其数组+链表/红黑树结构、哈希冲突解决和扩容机制体现了数据结构的设计思想。在技术价值层面,掌握核心概念能够提升代码质量和系统性能,特别是在高并发场景下的线程安全问题处理。应用场景涵盖互联网企业的后端开发、金融系统的交易处理等需要稳定性和性能保障的领域。本文基于2026年面试趋势,整合HashMap原理和JVM调优等热词,提供

weixin_30252709的博客 446

java集合——HashSet的用法

java集合——HashSet的用法 一、HashSet的构造 HashSet hashset=new HashSet(); 二、HashSet添加元素 //向hashset中添加一个字符串 hashset.add("abc"); //向hashset中添加一个整数 hashset.add(1); //向hashset中添加一个字符 hashset.add('a');

Lizhifun 11万+

集合的概述、集合的构造方法

hey,欢迎浏览我的博客,希望能给你提供帮助。 837

Java中的HashSet

原文地址:HashSet in JavaHashSet: 实现了Set接口 HashSet依赖的数据结构是哈希表 因为实现的是Set接口,所以不允许有重复的值 插入到HashSet中的对象不保证与插入的顺序保持一致。对象的插入是根据它的hashcode HashSet中允许有NULL值 HashSet也实现了Searlizable和Cloneable两个接口 HashSet的构造函数: Hash

K.Sun 9472

Java手撕面试官-面试官常问的Nginx的几个问题

1.什么是Nginx? Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器 目前使用的最多的web服务器或者代理服务器,像淘宝、新浪、网易、迅雷等都在使用 2.为什么要用Nginx? 优点: 跨平台、配置简单 非阻塞、高并发连接:处理2-3万并发连接数,官方监...

JavaWildcat的博客 755

JAVA高级架构师-浅析JavaWeb开发模式:Model1和Model2

一、前言 在学习JavaWeb的过程中,大家都会接触到Model1和Model2,历史的发展过程是Model1 → Model2。那么它们之间有何相同之处和不同之处呢? 二、Model1 Model1使用了两种技术:JSP+JavaBean。 在Model1模式下,整个Web应用几乎全部由JSP页面组成,JSP页面接受处理客户端请求,对请求处理后直接做出响应。用少量的J...

JavaWildcat的博客 667

深入理解Java虚拟机笔记---底层原理分析与性能优化

深入理解Java虚拟机笔记---底层原理分析与性能优化 文末彩蛋福利# 概念 虚拟机:指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现。常用的虚拟机有VMWare,Visual Box,Java Virtual Machine(Java虚拟机,简称JVM)。 Java虚拟机阵营:Sun HotSpot VM、BEA JRockit ...

JavaWildcat的博客 530

Java NIO ByteBuffer 的使用与源码研究

一、结论   ByteBuffer 是Java NIO体系中的基础类,所有与Channel进行数据交互操作的都是以ByteBuffer作为数据的载体(即缓冲区)。ByteBuffer的底层是byte数组,通过四个重要的成员变量(mark、limit、position、capacity)来实现对缓冲区的读写数据以及复用缓冲区等操作。ByteBuffer 申请缓冲区内存(数组)的方式有两种,即堆内...

JavaWildcat的博客 443

一个经典面试题:如何保证缓存与数据库的双写一致性?

只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 面试题剖析 一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去。 串行化可以保证一定不会出现不一致的情况,但是它也会导致系统的...

JavaWildcat的博客 428

Java高并发缓存架构,缓存雪崩、缓存穿透之谜

面试题 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你。 面试题剖析 缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4...

JavaWildcat的博客 414
上一篇: Java高并发缓存架构,缓存雪崩、缓存穿透之谜
下一篇: 阿里p7架构师带你领略JMM
程序员杨过
博客等级 码龄7年 13粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值