HashMap暴露了你的java基础功底

HashMap 常见问题Java8(扩容、转红黑树、退化链表、Hash优化) HashMap扩容 HashMap HashMap树化 HashMap退化链表 HashMap hash优化 HashMap put过程 HashMap 转红黑树条件 HashMap 循环异常 ConcurrentModificationException 红黑树、链表 阅读详情

(新建的群1039047324,欢迎对技术感兴趣的朋友加入,群内可以接私活,聊技术,分享工作中容易踩的坑,以及如何避免踩坑,分享最新架构视频)

1.HashMap的底层数据结构是什么?
底层数据结构是哈希表结构(链表散列:数组+单向链表),结合了数组和链表的优点,当链表长度超过8时,链表会转为红黑树。数组中的每一个元素都是链表。总结来说就是HashMap在JDK1.8之前底层是由数组+链表实现的,从JDK1.8开始底层是由数组+链表或者数组+红黑树实现的。

追问:为什么在1.8中增加红黑树?
当需要查找某个元素的时候,线性探索是最直白的方式,它会把所有数据遍历一遍直到找到你所查找的数据,对于数组和链表这种线性结构来说,当链表长度过长(数据有成百上千)的时候,会造成链表过深的问题,这种查找方式效率极低,时间复杂度是O(n)。简单来说红黑树的出现就是为了提高数据检索的速度,时间复杂度为O(logn)。比如,存储数据个数为256,使用红黑树遍历只需要8次。

继续追问:链表过深问题为什么不用二叉查找树代替,而选择红黑树?为什么不一直使用红黑树?
二叉树在特殊情况下会变成一条线性结构,这就跟原来的链表结构一样了,选择红黑树就是为了解决二叉树的缺陷。
红黑树在插入数据的时候需要通过左旋、右旋、变色这些操作来保持平衡,为了保持这种平衡是需要付出代价的。当链表很短的时候,没必要使用红黑树,否则会导致效率更低,当链表很长的时候,使用红黑树,保持平衡的操作所消耗的资源要远小于遍历链表锁消耗的效率,所以才会设定一个阈值,去判断什么时候使用链表,什么时候使用红黑树。

2.讲一下HashMap的工作原理,put()和get()的过程分别是怎么样的?
1 存储对象时,将key和vaule传给put()方法:

  1. 判断数组是否为空,为空进行初始化;
  2. 不为空,计算 k 的 hash 值,通过(n - 1) & hash计算应当存放在数组中的下标 index;
  3. 查看 table[index] 是否存在数据,没有数据就构造一个Node节点存放在 table[index] 中;
  4. 存在数据,说明发生了hash冲突(存在二个节点key的hash值一样), 继续判断key是否相等,相等,用新的value替换原数据(onlyIfAbsent为false);
  5. 如果不相等,判断当前节点类型是不是树型节点,如果是树型节点,创造树型节点插入红黑树中;(如果当前节点是树型节点证明当前已经是红黑树了)
  6. 如果不是树型节点,创建普通Node加入链表中;判断链表长度是否大于8并且数组长度大于64,大于的话链表转换为红黑树;
  7. 插入完成之后判断当前节点数是否大于阈值(capacity*loadFactor),如果大于开始扩容为原数组的二倍。

下面以流程图方式更加直观的看一下插入流程:

2 获取对象时,将key传给get()方法:

  1. 调用hash(key)方法获取key对应的hash值从而获取该键值对在数组中的下标。
  2. 对链表进行顺序遍历,使用equals()方法查找链表中相等的key对应的value值。

追问:说一下数组是怎么扩容的?
创建一个新数组,新数组初始化容量大小是旧数组的两倍,对原数组中元素重新进行一次hash从而定位在新数组中的存储位置,元素在新数组中的位置只有两种,原下标位置或原下标+旧数组的大小。
追问:为什么要对原数组中元素再重新进行一次hash?直接复制到新数组不行吗?
因为数组长度扩大以后Hash规则也会随之变化。
Hash的公式—> index = HashCode(Key) & (Length - 1)
追问:在插入元素的时候,JDK1.7与JDK1.8有什么不同?
1.7是先判断是否需要扩容,再进行插入操作。1.8是先插入,插入完成之后再判断是否需要扩容。
注:hashcode是用来定位的,定键值对在数组中的存储位置。equals()方法是用来定性的,比较两个对象是否相等。 

 3.你说JDK1.8之前使用头插法将Entry节点插入链表,那么头插法具体是怎么做的?设计头插法的目的是什么?

新值会作为链表的头部替换原来的值,原来的值会被顺推到链表当中。下面以图解方式说明一下:

设计者认为后来插入的值被查找的概率比较高,使用头插法可以提高查找的效率。

追问:那么,在HashMap中,到底是怎样形成环形链表的?

JDK7 中 HashMap 成环原因

成环的时机

1:HashMap 扩容时。

2:多线程环境下。

当多个线程同时对这个HashMap进行put操作,而察觉到内存容量不够,需要进行扩容时,多个线程会同时执行resize操作,而这就出现问题了,问题的原因分析如下:

首先,在HashMap扩容时,会改变链表中的元素的顺序,将元素从链表头部插入。

重点就在这个transfer()中:

  经过这几步,我们会发现转移的时候是逆序的。假如转移前链表顺序是1->2,那么转移后就会变成2->1。这时候就有点头绪了,死锁问题不就是因为1->2的同时2->1造成的吗?所以,HashMap 的死锁问题就出在这个transfer()函数上。

假设原来oldTable里存放a,b的hash值是一样的,那么entry链表顺序是:
       P1:oldTable[i]->a->b->null                 P2:oldTable[i]->a->b->null
 线程P1运行到上面595行时,e=a(a.next=b),继续运行到597行时,next=b。这个时候切换到线程P2,线程P2执行完这个链表的循环。如果恰a,b在新的table中的hash值又是一样的,那么此时的链表顺序是: 
       主存:newTable[i]->b->a->null
       注意这个时候,a1,a2连接顺序已经反了。现在cpu重新切回P1,在第602行以后:e.next = newTable[i];即:              a1.next=newTable[i];
       newTable[i]=a1;
       e=a2;
       开始第二次while循环(e=a2,next=a1):
       a2.next=newTable[i];//也就是a2.next=a1
       newTable[i]=a2
       e=a1
       开始第三次while循环(e=a1,next=null)
       a1.next=newTable[i];//也就是a1.next=a2
       这个时候a1.next=a2,a2.next=a1,形成回环了,这样就造成了死循环,在get操作的时候next永远不为null,造成死循环。
       put()过程造成了环形链表,但是它没有发生错误。一旦再调用get()就悲剧了。
       可以看到很偶然的情况下会出现死循环,不过一旦出现后果是非常严重的,多线程的环境还是应该用ConcurrentHashMap。
4.HashMap是怎么设定初始化容量大小的?
使用new HashMap()不传值,默认大小是16,负载因子是0.75。如果传入参数K,那么初始化容量大小为大于K的2的最小整数幂。比如传入的是10,那么初始化容量大小就是16(2的4次方)。
追问:为什么HashMap的数组长度要取2的整数幂?
因为这样数组长度-1正好相当于一个“低位掩码”。“与”操作的结果就是散列值的高位全部归零,只保留低位值,用来做数组下标访问。以初始长度16为例,16-1=15。2进制表示是00000000 00000000 00001111。和某散列值做“与”操作如下,结果就是截取了最低的四位值。

5.讲一下HashMap中的哈希函数时怎么实现的?
key的hashcode是一个32位的int类型值,hash函数就是将hashcode的高16位和低16位进行异或运算。
追问:哈希函数为什么这么设计?
这是一个扰动函数,这样设计的原因主要有两点:

可以最大程度的降低hash碰撞的概率(hash值越分散越好);
因为是高频操作,所以采用位运算,让算法更加高效;

6.HashMap是线程安全的吗?
不是,在多线程的情况下,1.7的HashMap会导致死循环、数据丢失、数据覆盖。在1.8中如果有多个线程同时put()元素还是会存在数据覆盖的问题。以1.8位例,A线程判断index位置为空后正好挂起,B线程开始向index位置写入节点数据,这时A线程恢复现场,执行赋值操作,就把A线程的数据给覆盖了。
追问:如何解决这个线程不安全的问题?
可以使用HashTable、Collections.synchronizedMap、以及ConcurrentHashMap这些线程安全的Map。
追问:分别讲一下这几种Map都是如何实现线程安全的?
HashTable是直接在操作方法上加synchronized关键字,锁住整个数组,粒度比较大;
Collections.synchronizedMap是使用Collections集合工具的内部类,通过传入Map封装出一个SynchronizedMap对象,内部定义了一个对象锁,方法内通过对象锁实现;
ConcurrentHashMap在JDK1.7中使用分段锁,降低了锁粒度,让并发度大大提高,在JDK 1.8 中直接采用了CAS(无锁算法)+ synchronized的方式来实现线程安全。

7.说一下HashMap在JDK1.8中都有哪些改变?

  1. 底层数据结构:1.7中是数组+链表。1.8中是数组+链表或数组+红黑树;
  2. 元素插入方式:1.7是头插法插入链表。1.7是尾插法插入链表;
  3. 节点类型:1.7中数组中节点类型是Entry节点,1.8中数组中节点类型是Node节点;
  4. 元素插入流程:1.7中是先判断是否需要扩容,再插入。1.8中是先插入,插入成功之后再判断是否需要扩容;
  5. 扩容方式:1.7中需要对原数组中元素重新进行hash定位在新数组中的位置。1.8中采用更简单的逻辑判断,原下标位置或原下标+旧数组的大小。

8.HashMap的内部节点是有序的吗?
是无序的,根据hash值随机插入。
追问:你知道哪些有序的Map?
LinkedHashMap和TreeMap。
追问:说一下这两种Map分别是怎么实现有序的
LinkedHashMap: LinkedHashMap内部维护了一个单链表,有头尾节点,同时LinkedHashMap节点Entry内部除了继承HashMap的Node属性,还有before 和 after用于标识前置节点和后置节点。可以实现按插入的顺序或访问顺序排序。
TreeHashMap: TreeMap是按照Key的自然顺序或者Comprator的顺序进行排序,内部是通过红黑树来实现。所以要么key所属的类实现Comparable接口,或者自定义一个实现了Comparator接口的比较器,传给TreeMap用于key的比较。


9 .HashMap,LinkedHashMap,TreeMap 有什么区别?
LinkedHashMap 保存了记录的插入顺序,在用 Iterator 遍历时,先取到的记录肯定是先插入的;遍历比 HashMap 慢。TreeMap 实现 SortMap 接口,能够把它保存的记录根据键排序(默认按键值升序排序,也可以指定排序的比较器)
追问:讲一下这三种Map的使用场景
一般情况下,使用最多的是 HashMap。
HashMap:在 Map 中插入、删除和定位元素时;
TreeMap:在需要按自然顺序或自定义顺序遍历键的情况下;
LinkedHashMap:在需要输出的顺序和输入的顺序相同的情况下。

ArrayList、LinkedList、HashMap、HashTable、HashSet、TreeSet 阅读详情

相关推荐

解决Java HashMap线程安全问题的方法指南

htmltable {th, td {th {pre {简介:HashMap在Java中用于存储键值对,但非线程安全导致并发访问时可能出现数据不一致和结构混乱。本指南介绍HashMap线程安全问题的原因,并提供多种解决方案,包括使用Collections.synchronizedMap()、ConcurrentHashMap、HashTable或避免在多线程环境下使用HashMap,帮助开发者在不同场景下选择合适的线程安全措施,确保Java程序稳定运行。

weixin_29859471的博客 1056

hashmap相关

HashMap集合简介 HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。 JDK1.8 之前 HashMap 由 数组+链表 组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突(两个对象调用...

weixin_44187446的博客 1369

[基于STM32底盘控制与ROS上层导航小车制作] 第一节 stm32电机驱动与编码器读取反馈

系列文章目录 第一节stm32电机驱动与编码器读取反馈 第二节 stm32电机pid控制 第三节 stm32线速度标定 第四节 stm32添加mpu6050得到angle角度 第五节 实现STM32与ubuntu系统下的ROS串口DMA通信,传输底盘速度等信息 第六节 ROS计算和发布里程计 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 系列文章目录 前言 1.pwm与电机正反转 2.编码器初始化 二、pwm控制与编码器使用 1.pwm使电机 .

LanLanLan1927的博客 1万+

HashMap 容量设置-什么时候初始化

HashMap 容量设置问题的分析前言问题剖析源码分析初始化存放元素resize()总结 前言 最近 在看 HashMap 看到一个问题: HashMap 初始容量设置为 10000 时,放入 10000 条数据是否需要扩容;如果初始容量设置为 1000 时,放入 1000 条数据是否需要扩容? 不知道有多少小伙伴 能回答出这个问题哈 问题剖析 看到这个问题 我一开始也不知道,但是从题目中 我们可以看出 初始容量的设置大小 对后面的 存放数据的多少 一定有影响 不然问题也不会这么问。 我们知道

zxlp520的博客 1821

AWS 小白书 [1] 全球架构

小白应该知道的 AWS 知识

boshansolo的博客 707

Excel聚光灯效果终极指南:VBA代码实现与条件格式避坑技巧

本文详细解析了Excel聚光灯效果的实现方法,包括VBA代码优化与条件格式的避坑技巧。通过模块化编程和性能优化技术,帮助用户高效处理大型数据表格,实现自定义高亮显示,提升数据分析和报表阅读体验。

v6b7n8m9q0的博客 458

* java版HashMap,大数据量时效率很低,建议1000条数据以下使用

/*  * java版HashMap,大数据量时效率很低,建议1000条数据以下使用  */ function HashMap(){         var DEFAULT_CAPACITY=16;     var MAX_CAPACITY=2147483647;     var DEFAULT_LOAD_FACTOR=0.75;     /************ splitl

skiof007的专栏 9781

机器人视觉联动精度优化:从±2mm到±0.02mm,产线级手眼标定全实战

2025年我接东莞长安Type-C接口分拣项目的时候,就是栽在了手眼标定上:实验室里标定完精度±0.5mm,一到产线直接掉到±2mm,机器人10次有3次抓不住,2000多件Type-C接口直接报废,还撞坏了2套汇川SCARA机器人的吸盘,本来45天的工期拖了3个月,不仅没赚到钱,还倒贴了几万块。手眼标定从来不是简单的跑个demo、算个矩阵就完事了,它是一个系统工程:从硬件选型、安装固定、相机标定、标定流程、算法优化、环境控制、重复验证,每一个环节都会影响最终的联动精度。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 389

HashMap的数据结构

结果是这个树大致上是平衡的。9、将 Node 存入链表之后,判断链表的结构是否要调整,判断链表长度是否超过 8,如果超过 8 需要将链表转为红黑树,这里还有一个条件,如果数组的容量小于64,不转换红黑树,而是进行数组扩容,当数组的容量大于 64 的时候,再将链表转为红黑树。的数据结构,通过计算的Hash值找到数组上的位置,如果出现Hash相同的情况,依然会出现Hash碰撞,如果数组位置上没有元素,则直接将这个元素放到数组位置上,如果有元素则会向下延伸出链表,不过新的元素会放到链表的尾部,即尾插法。

m0_68529003的博客 1992

STM32 USB键盘实现指南

在STM32上实现键盘功能可以通过USB HID(人机接口设备)协议来实现,使STM32设备能被计算机识别为标准键盘。通过上述步骤,您可以在STM32上实现一个功能完整的USB键盘。关键点包括:正确配置USB HID设备实现键盘矩阵扫描处理按键事件并生成HID报告优化按键响应和消抖处理添加额外功能如宏键和LED反馈这个实现可以作为基础,进一步扩展为游戏键盘、宏键盘或特殊输入设备。

suny8的专栏 975

Dify平台隐患url:/console/api/remote-files/upload暴露高危漏洞,配置nginx htpasswd模块认证机制屏蔽解决

内部网络探测: 攻击者可通过SSRF扫描内网服务云元数据访问: 可能访问AWS/Aliyun/腾讯云等元数据服务服务端请求伪造: 以服务器身份发起任意HTTP请求。

CN_Eden 1325

HashMap扩容resize流程

resize函数触发时机: 1.初始化HashMap的默认扩容一个cap为16 threshold为12的Node<K, V>[] newTab 2.当hashMap的size>threshold的时候再次扩容,扩容为16*2的cap,threshold*2的Node<K, V>[] newTab 3.当table中Node链表大于8且tab.length小于64的时候,hash再次double扩容 下面直接上流程图 第一阶段:主要为计算出新的newCap(扩容.

IFuZzz的博客 2041

135、高通 ChromaTix 调优工具入门:参数含义、调优流程与效果对比

本文介绍了高通ChromaTix色彩调优工具的核心使用要点:1. ChromaTix是位于ISP管线中的色彩处理系统,核心任务是将原始色彩映射为符合人眼感知的"舒适"效果;2. 重点解析了饱和度、色调、亮度相关饱和度等关键参数的实际含义和调试陷阱;3. 分享了四步调优流程,强调需要基于多场景数据验证;4. 通过案例展示了参数调整带来的色彩改善效果;5. 总结了实用建议,包括保持单一变量调试、量化评估色差、关注极端场景表现等。文章指出ChromaTix调优是平衡不同场景需求的"妥协艺术",需要结合客观数据和主

sundong_81的博客 111

java暴露方法_java基础之Dubbo服务暴露分析

Dubbo的服务暴露是一个重要的特性,了解其机制很重要。之前有很多人写了有关的源代码分析,在本文中不再重新分析。官方文档中的一篇写的就很好,本文主要是有关内容进行补充与总结。传送门:服务导出1|0为什么要服务暴露服务暴露分为远程暴露和本地暴露。在远程服务暴露中会将服务信息上传到注册中心。这时客户端要调用某个服务时会从注册中心找到该服务的远程地址等信息。然后客户端根据这个地址进行远程调用。服务端接收...

weixin_30476033的博客 596

数据库系统概论第五版课后习题答案第十二章

对元组的插入、删除、修改;语义检查的具体做法是,DBMS读取数据字典,检查是否存在与该语句中的表、视图或索引等要创建的对象相同的对象名,检查该用户是否具有创建数据库对象的权限。答:操作系统提供的封锁机制和DBMS的封锁机制在封锁对象、封锁对象的状态、封锁的粒度、及封锁的类型上存在很大的差别,操作系统的封锁机制不能直接应用在DBMS中,DBMS必须重新设计,来满足复杂的封锁需求。数据库的建立和维护包括数据库的初始建立、数据的转换、数据库的转储和恢复、数据库的重组织和重构造以及性能监测分析等功能。

wenling54321的博客 695

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

实习生面试复盘:技术面中暴露的基础薄弱环节整理

面试复盘的最大价值不是数自己答错了多少题,而是确认自己的知识断层在哪里。不是背更多新概念,而是把已经知道的概念往深处挖一层。用"为什么这样设计"代替"是什么":每个知识点都追问自己一句"为什么是这样,而不是那样"画调用链路图:把源码的关键方法之间的调用关系画出来,比纯看源码效率高对每一个常用 API 读 30 分钟源码:不需要全懂,但要知道核心的实现思路面试中的追问没有标准终点,但如果你能把每个答案延伸到"机制层",基本就能应对大厂 90% 的技术追问。

cannonjinx的博客 4762

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

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

Java测验1:一次基础自测暴露的五个隐藏问题

Java是企业级开发的主流语言,其基础知识的扎实程度直接决定技术成长的天花板。面向对象、集合框架、异常机制、JVM内存与并发等核心概念构成了Java技术体系的基石。理解这些底层原理,不仅能高效排查数组越界异常、OutOfMemoryError等常见运行错误,还能在准备java面试题时,避免陷入java八股文的机械记忆。本文通过一次Java基础测验,深度解析了String对象创建、HashMap与Hashtable区别、接口与抽象类选择、Lambda有效final限制、finally与return关系等高频易

weixin_29973493的博客 310

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

map hashmap的使用

map hashmap的使用 package map; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Map的实现类HashMap使用 */ public class MapTest { /**...

u013165852的博客 162

java基础进阶丨理解并实现HashMap

前言 HashMap是Java中常用的集合,而且HashMap的一些思想,对于我们平时解决业务上的一些问题,在思路上有帮 助,基于此,本篇博客将分析HashMap底层设计思想,并手写一个迷你版的HashMap! 对HashMap的思考 HashMap底层数据结构 第一,如图所示,HashMap有3个要素:hash函数+数组+单链表 第二,对于hash函数而言,需要考虑些什么? 要快,对于给定的Key,要能够快速计算出在数组中的index。那么什么运算够快呢?显然是位运算! 要均匀分布,要较

无发可说的博客 257

hashmap put复杂度_通过一个实际案例,彻底搞懂 HashMap

Java大联盟 帮助万千Java学习者持续成长关注作者|邵磊juejin.im/post/59bc601ff265da0652708abd 前言我知道大家都很熟悉hashmap,并且有事没事都会new一个,但是hashmap的一些特性大家都是看了忘,忘了再记,今天这个例子可以帮助大家很好的记住。场景用户提交一张试卷答案到服务端,post报文可精简为[{"question_id...

weixin_32349699的博客 998

谢飞机的Java大厂面试记:从HashMap到DDD的爆笑技术拷问

一篇以幽默故事形式讲解Java核心技术面试题的文章,涵盖JUC、JVM、Spring生态、中间件、数据库及架构设计等高频考点,附详细解析,助小白系统掌握面试重点。

sonicxia的博客 571

Java:深入理解HashMap

文章目录前言一、HashMap插入节点的流程二、如何优化哈希碰撞三、哈希表如何优化四、HashMap线程安全问题五、HashMap 与HashTable的区别六、HashMap 与SparseArray的区别二、使用步骤1.引入库2.读入数据总结 前言 一、HashMap插入节点的流程 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、如何优化哈希碰撞 三、哈希表如何优化 四、HashMap线程安全问题 五、HashMap 与HashTable的区别 Hash

qjyws的博客 887

【java】面试经典之hashmap解读,并简单手写一个hashmap

HashMap是在面试中经常会问的一点,很多时候我们仅仅只是知道HashMap他是允许键值对都是Null,并且是非线程安全的,如果在多线程的环境下使用,是很容易出现问题的。 这是我们通常在面试中会说的,但是有时候问到底层的源码分析的时候,为什么允许为Null,为什么不安全,这些问题的时候,如果没有分析过源码的话,好像很难回答, 这样的话我们来研究一下这个源码。看看原因吧。 ...

wphero的博客 1393

Java基础知识点汇总

Java基础知识点汇总1. Java基础语法2. 面向对象3. 异常处理4. 集合5. IO流 1. Java基础语法 类型转换 // 强制类型转换 float a = 20.34f; int b = (int)a; //自动类型转换 int c = 10; float d = c; //操作较大的数时,注意溢出问题 //JDK7新特性,数字之间可以用下划线分割

qq_41286666的博客 5万+

手写实现一个HashMap

手写实现一个HashMap 前言 HashMap是Java中常用的集合,而且HashMap的一些思想,对于我们平时解决业务上的一些问题,在思路上有帮助,基于此,本篇博客将分析HashMap底层设计思想,并手写一个迷你版的HashMap! 对HashMap的思考 HashMap底层数据结构 第一,如图所示,HashMap有3个要素

huangshulang1234的博客 1万+

(转)Java中hashset和hashMap的区别

出处声明 本文转自http://www.cnblogs.com/xinzhao/p/5644175.html,感谢作者的分享。 HashMap和HashTable有什么不同?在面试和被面试的过程中,我问过也被问过这个问题,也见过了不少回答,今天决定写一写自己心目中的理想答案。 代码版本 JDK每一版本都在改进。本文讨论的HashMap和HashTable基于JDK 1.7.0_67。源码见这里 ...

Andy的博客 2864
上一篇: 消息队列面试总结
下一篇: java基础一点也不基础
微服务架构
博客等级 码龄10年 15粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值