Java数据结构8(map和set)

java1.8流式用法-工作使用总结经验 工作中经常需要用到流的用法,通过使用流让程序的阅读性更强,代码更简洁。 阅读详情

目录

1,搜索树

2,哈希表

3,注意点

一,搜索树

1,前提引入

可以通过这张表看出,set和map分别都有通过红黑树或者哈希表来实现的,我们先从红黑树来讲起,红黑树的底层就是搜索树,我们先自己从自己创建的搜索树开始

2,概念

可以是一颗空树,或者具有这些性质:左边的都比根结点要小,右边都比根结点要大

3,方法的实现

(1)查询

 //查找
    public static TreeNode search(TreeNode root,int key){
        if (root==null){
            return null;
        }
        TreeNode cur=root;
        while (cur!=null){
            if (key>cur.val){
                cur=cur.right;
            }else if (cur.val==key){
                return cur;
            }else {
                cur=cur.left;
            }
        }
        return null;
    }

(2)增加元素

 //增加元素
    public static void insert(TreeNode root,int key){
        if (root==null){
            root=new TreeNode(key);
        }
        TreeNode node=new TreeNode(key);
        TreeNode cur=root;
        TreeNode parent=null;
        while (cur!=null){
            if (key>cur.val){
                parent=cur;
                cur=cur.right;
            }else if (cur.val==key){
                return;
            }else {
                parent=cur;
                cur=cur.left;
            }
        }
        if (parent.val>key){
            parent.left=node;
        }else if (parent.val<key){
            parent.right=node;
        }
    }

(3)删除元素

//删除
    public static void remove(TreeNode root,int key){
        if (root==null){
            return;
        }
        TreeNode cur=root;
        TreeNode parent=null;
        //先要找到cur的位置在进行删除
        while (cur!=null){
            if (key> cur.val){
                parent=cur;
                cur=cur.right;
            }else if (key==cur.val){
                removecur(parent,cur);
                return;
            }else{
                parent=cur;
                cur=cur.left;
            }
        }
    }

    private static void removecur(TreeNode parent, TreeNode cur) {
        //核心就是要让变的部分等于cur.right
        if (cur.left==null){
            //cur为root
            if (cur==root){
                root=cur.right;
            }else if (cur==parent.left){
                parent.left=cur.right;
            }else if (cur==parent.right){
                parent.right=cur.right;
            }
        }//核心就是要让变的部分等于cur.left
        else if (cur.right==null){
            if (cur==root){
                root=cur.left;
            }else if (cur==parent.left){
                parent.left=cur.left;
            }else if (cur==parent.right){
                parent.right=cur.left;
            }
        }//左右都不为空的情况
        //我们选择替换->让右边的最左树替换掉cur
        else {
            TreeNode target=cur.right;
            TreeNode targetparent=cur;
            while (target.left!=null){
                targetparent=parent;
                target=target.left;
            }
            cur.val=target.val;
            //也就是有左树
            if (target==targetparent.left){
            targetparent.left=target.right;
            }//没有左树,只有右树,那么target就是合适的替换人选
            else {
                targetparent.right=target.right;
            }

        }
    }

4,模型的介绍

(1)K 模型(只存 Key,对应 Set)

容器里只存储关键字 Key,没有配套的 value,唯一作用:判断某个 key 是否存在、自动去重。

(2)KV 模型(Key+Value 成对存储,对应 Map)

容器存储一对数据 <Key, Value>,key 唯一,value 是 key 附带的业务信息,通过 key 快速查找对应 value。

map的存储是kv模型,而set是纯k模型

5,treemap的方法实现

(1)常见的方法:

方法名解释
get(Object key)返回 key 对应的 value
getOrDefault(Object key, V defaultValue)返回 key 对应的 value,key 不存在,返回默认值
put(K key, V value)设置 key 对应的 value
remove(Object key)删除 key 对应的映射关系
keySet()返回所有 key 的不重复集合
values()返回所有 value 的可重复集合
entrySet()返回所有的 key-value 映射关系
containsKey(Object key)判断是否包含 key
containsValue(Object value)判断是否包含 value
Map.Entry<a,b>是map内部类用来实现存放kv键值对映射关系的内部类,下面的方法只有单个map.entry才能实现,用set来点是可以发现没有对应的方法的,因为我下面代码中的set已经表达的是一个map.entry的一个集合,里面装着左右的map.entry,所以我们要拿出一个的话可以使用循环或者迭代器来实现
方法解释
K getKey()返回 entry 中的 key
V getValue()返回 entry 中的 value
V setValue(V value)将键值对中的 value 替换为指定 value
public static void main(String[] args) {
        Map<String,Integer> map=new TreeMap<>();
        map.put("ab",1);
        map.put("cd",2);
        map.put("ef",2);
        map.put("hello",5);
        Set<String> strings=map.keySet();
        System.out.println(strings);
        Collection<Integer> collection=map.values();
        System.out.println(collection);
        Set<Map.Entry<String,Integer>> set=map.entrySet();
        for (Map.Entry<String, Integer> entry :
                set) {
            System.out.println("key:"+entry.getKey()+" "+"val:"+entry.getValue());
        }
        //System.out.println(set);
    }

(2)注意点

1,Map是⼀个接⼝,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者 ,HashMap 

2,Map中存放键值对的Key是唯⼀的,value是可以重复的 

3,在TreeMap中插⼊键值对时,key不能为空,否则就会抛NullPointerException异常,value可以
为空。但是HashMap的key和value都可以为空。
4,Map中的Key可以全部分离出来,存储到Set中来进⾏访问(因为Key不能重复)。
5, Map中的value可以全部分离出来,存储在Collection的任何⼀个⼦集合中(value可能有重复)。
6,Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进⾏重新插⼊。

6,treeset的方法实现

(1)常见的方法:

方法解释
boolean add(E e)添加元素,重复元素不会添加成功
void clear()清空集合中所有元素
boolean contains(Object o)判断元素 o 是否存在于集合
Iterator<E> iterator()返回集合的迭代器,用于遍历元素
boolean remove(Object o)删除集合中的指定元素 o
int size()返回集合内元素的总个数
boolean isEmpty()判断集合是否为空,空返回 true,否则 false
Object[] toArray()将集合所有元素转为 Object 数组并返回
boolean containsAll(Collection<?> c)判断传入集合 c 的所有元素是否都在当前 Set 中,全部存在返回 true
boolean addAll(Collection<? extends E> c)将集合 c 全部元素添加进当前 Set,自动去重
public static void main(String[] args) {
        Set<Integer> set=new TreeSet<>();
        set.add(2);
        set.remove(2);
        System.out.println(set.contains(2));
    }

(2)注意点

1,key要唯一

2,本质也就是treemap,treemap里面的key就是唯一的,所以也就相当于是对应的,但是treemap里面不是还有一个val项,treeset默认传给一个object类

二,哈希表

1,概念

我们通过哈希函数来放数据,构造出来的结构称为哈希表

我们常用的函数为key/capacity

2,冲突-避免

面对上面说的冲突,我们有避免和解决两种方法,我们首先来讲避免

(1)改善哈希函数

面对不同的要求,我们可以定制不同的哈希函数,但是哈希函数一般我们都不会去改变他,我们都是用的常用的,也就是除留余数法:key/capacity

(2)调节负载因子

散列表的负载因子:填入表中的元素个数/散列表的长度

负载因子和冲突率的函数图:

可以发现负载因子越大,冲突率越大

3,冲突-解决

解决我们一般有两种方法:闭散列和开散列

(1)闭散列

(1.1)线性探测

直接理解就是我们找到冲突后面的第一个空的元素填进去

这样会导致冲突的元素都聚集在一起,删除元素的时候会很麻烦,因为如果我们要删除4的时候,4下标的位置就空出来了,当我们要找14的时候,我们理应根据公式找到4下标,但是我们会发现4下标是没有的,所以这时候我们要删除的时候要标记一下那个下标是否已经被删除过了

(1.2)二次探测

这个方法比线性探测好一点,但是元素多了也会导致矛盾元素的聚集,也称为二次聚集,也不太好

(2)开散列(重点)

开散列是我们重点要掌握的方法,也俗称哈希桶

(3)自己实现的哈希桶

我们插入方法选择头插法

1,int类型
public class HushBuck {
    static class Node{
        //成员
        public int key;
        public int val;//默认给999
        public Node next;
        //构造方法
        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    public static Node[] array;
    public int usedSize;
    public static final double LOAD_FACTOR = 0.75;
    public  HushBuck(){
       array=new Node[10];
    }
    public void push(int key, int val){
        //确定下标
        int index=key%array.length;
        //更新val
        Node cur=array[index];
        while (cur!=null){
            if (cur.key==key){
                cur.val=val;
                return;
            }
            cur=cur.next;
        }
        //头插法
        Node newNode=new Node(key, val);
        newNode.next=array[index];
        array[index]=newNode;
        usedSize++;
        //确认负载因子
        if (usedSize*1.0/array.length>=LOAD_FACTOR){
            //进行扩容并且重新哈希
            resize();
        }
    }
    private void resize(){
        Node[] newArray=new Node[array.length*2];
        for (int i = 0; i < array.length; i++) {
            Node cur=array[i];
            while (cur!=null){
                int newIndex=cur.key%newArray.length;
                Node curN=cur.next;
                cur.next=newArray[newIndex];
                newArray[newIndex]=cur;
                cur=curN;
            }
        }
        array=newArray;
    }
    public int get(int key){
        int index = key % array.length;
        Node cur = array[index];
        while (cur != null) {
            if(cur.key == key) {
                return cur.val;
            }
            cur = cur.next;
        }
        return -1;
    }


}
2,泛型
public class HushBuck2 <K,V>{
    static class Node<K,V>{
        //成员
        public K key;
        public V val;//默认给999
        public Node<K,V> next;
        //构造方法
        public Node(K key, V val) {
            this.key = key;
            this.val = val;
        }
    }
    public  Node<K,V>[] array;
    public int usedSize;
    public static final double LOAD_FACTOR = 0.75;
    public  HushBuck2(){
        array=(Node<K,V>[]) new Node[10];
    }
    public void push(K key, V val){
        //确定下标
        int hash=key.hashCode();
        int index=hash%array.length;
        //更新val
        Node<K,V> cur=array[index];
        while (cur!=null){
            if (cur.key.equals(key)){
                cur.val=val;
                return;
            }
            cur=cur.next;
        }
        //头插法
        Node<K,V> newNode=new Node<K,V>(key, val);
        newNode.next=array[index];
        array[index]=newNode;
        usedSize++;
        //确认负载因子
        if (usedSize*1.0/array.length>=LOAD_FACTOR){
            //进行扩容并且重新哈希
            resize();
        }
    }
    private void resize(){
        Node<K,V>[] newArray=new Node[array.length*2];
        for (Node<K, V> kvNode : array) {
            Node<K, V> cur = kvNode;
            while (cur != null) {
                int newIndex = cur.key.hashCode() % newArray.length;
                Node<K, V> curN = cur.next;
                cur.next = newArray[newIndex];
                newArray[newIndex] = cur;
                cur = curN;
            }
        }
        array=newArray;
    }
    public V get(K key){
        int index = key.hashCode() % array.length;
        Node<K,V> cur = array[index];
        while (cur != null) {
            if(cur.key.equals(key)) {
                return cur.val;
            }
            cur = cur.next;
        }
        return null;
    }

}

三,注意点

1,hashcode 和 equals 的区别:

当我们想加自己写的类的时候,我们需要再类里面重写hashcode和equals方法,保证一样的key哈希出来的值是一样的

(1)equals 负责判断内容相等;

(2)hashCode 负责哈希容器快速分区;

(3)相等对象哈希值必须相同,哈希值相同对象不一定相等;

(4)重写 equals,一定要同步重写 hashCode,否则哈希集合失效。

2,系统里的哈希方法只有在你put的时候才会第一次定义数组的长度,才会分配内存,调用不带参数的构造方法,第一次的容量会是16,用带参数传容量的构造方法,会给到最接近你数字的二次幂,比如你给15,会给你16,你要20,会给你32

3,当你扩容的时候记得要二次哈希

车辆动力学从入门到进阶之路(传统篇) 新手如何入门车辆动力学开发领域,本文为您引路! 阅读详情

相关推荐

I2C总线原理及总线信号的实现

I2C总线是一种多主机总线,连接IIC总线上的器件分为主机和从机,主机有权发起和结束一次通信,而从机只能被主机呼叫;当总线上有多个主机同时启用总线时,I2C也具备冲突检测和仲裁的功能来防止错误产生;每个连接到IIC总线上的器件都有一个唯一的地址(7bit),且每个器件都可以作为主机也可以作为从机(同一时刻只能有一个主机),总线上的器件增加和删除不影响其他器件正常工作;I2C总线在通信时总线上发送数据的器件为发送器,接收数据的器件为接收器;主要用于近距离(抗干扰能力稍弱),低速的芯片之间的通信(传输视频,带宽

YLG_lin的博客 3944

【Java 8 新特性】Java forEach使用示例

【Java 8 新特性】Java forEach示例1.在`Iterable`中使用`forEach()`方法 forEach方法迭代源元素并执行给定的操作。 在Java8中,Iterable接口引入forEach作为默认方法,接受该函数作为Consumer,Map接口也引入forEach作为默认方法,接受该函数作为BiConsumer。 在Java8中,Stream也有forEach方法,接受该函数作为Consumer。Iterable接口由Collection扩展,因此forEach方法可用于List、

猫巳的博客 7524

高数 | 【极限与等价无穷小】两个重要极限 & 经典错误 & 什么情况下求极限可以直接带入

一. 第一个重要极限 二. 第二个重要极限 三. 导数定义式 全文见【高等数学】两个重要的极限 - 知乎

"You are worthy! You can do it!" 6万+

JAVA 8 LIST<对象> 转换SET

//list对象 转换Set Set<String> collect = users.stream().map(User ->User.getUserName()).collect(Collectors.toSet());

诚的博客 5148

Cadence17.2 > Allegro > 检查PCB Layout信号线组等长

Cadence17.2 > Allegro > 检查PCB Layout等长和配线

DL_62532的专栏 1万+

AGV、RGV、四向车openTCS调度系统(三)车辆适配器解读,封装自己的适配器

AGV、RGV、四向车调度。理解适配器的整体作用,以及如何使用官方例子改造自己的适配器,

要这头发有何用 3613

Java常见数据结构的遍历方式

方式二:遍历entrySet()集合直接获取K,V键值对,entry对象提供getKey()和getValue()方式一:遍历value()的值集合,此方法无法获取key值。方式一:遍历keySet()集合获取key值并二次取值。方式四:StreamApi(Java8以上版本支持)方式二:StreamApi(Java8以上版本支持)Java常见数据结构的遍历方式。方式二:forEach。方式二:forEach。

jiang_sync_yawn的博客 203

DIY电子管耳放实战:12AU7+6V6GT组合的电路设计与调试心得

本文详细分享了DIY电子管耳放的实战经验,重点解析了12AU7与6V6GT经典组合的电路设计、元件选型与调试过程。内容涵盖从核心架构设计、关键元件(如输出变压器、耦合电容)的科学选型,到静态工作点设置、负反馈引入及常见噪声问题的排查,旨在帮助音响DIY爱好者和电子管放大器初学者成功打造一台低失真、高信噪比且富有“胆味”的耳机放大器,享受动手制作的乐趣与温暖音质。

weixin_29230805的博客 555

集合篇总结——Set和Map接口

集合篇总结——Set和Map接口

Demon_and_Angle_的博客 305

ArcGIS实战:地形湿度指数(TWI)计算全流程解析

本文详细解析了ArcGIS中地形湿度指数(TWI)的计算全流程,从DEM数据获取、填洼处理到水流方向与汇流累积量计算,最终实现TWI的精准计算。通过实战步骤指导,帮助读者掌握水文建模和土壤湿度预测的关键技术,适用于农业规划、生态研究等领域。

weixin_29231725的博客 871

Halcon图片拼接避坑指南:特征点匹配常见问题与解决方案

本文深入解析Halcon图片拼接中特征点匹配的常见问题与解决方案,涵盖特征点提取、匹配优化及变换模型选择等关键环节。针对工业视觉检测中的拼接错位、重影等问题,提供参数调优、图像预处理和算法选择等实战技巧,帮助开发者高效避坑并提升拼接精度。

weixin_28694169的博客 199

【函数式编程实战】(七) Collection在Java8和9中的增强

Collection、Map API在java8以后的版本重大更新就是引入了流,添加了多个默认方法,例如Arrays.asList、.of、remove*、replace*、sort、forEach、merge等等,介绍了变化最大的一个数据结构ConcurrentHashMap

小明的Java问道之路 1564

使用R语言整理GEO数据的简易教程

本教程介绍了使用R语言从GEO数据库下载数据并进行数据整理的基本步骤。根据实际研究问题,你可能需要进行更复杂的数据处理和分析。R语言作为一种强大的生物信息学工具,为GEO数据的整理、分析和可视化提供了丰富的功能和工具。希望这个教程能够帮助你入门GEO数据整理和R语言的应用。如果你在使用过程中遇到问题,或需要进一步的指导,请随时向我询问。祝你在GEO数据分析的旅程中取得成功!

Mrrunsen的博客 3743

List与Map

Java8变成链表和红黑树的组合,数据少量存入的时候优先还是链表,当链表长度大于8,且总数据量大于64的时候,链表就会转化成红黑树,所以你会看到Java8的Hashmap的数据存储是数组+链表+红黑树的组合,如果数据量小于64则只有数组+链表,如果数据量大于64,且某一个数组下标数据量大于8,那么该处即为红黑树。Map集合它提供了一个键映射到值的一个数据结构,记住map的值是个重复,但键是唯一的,Map的子类有很多比如创建的是HashMap和LinkedHashMap。

wkywky123的博客 265

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

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

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

Java中的List、Set、Map面试常问知识点总结

一:集合结构 1:List: 有序(元素存入集合的顺序和取出的顺序已知)、可以重复存储、具有索引下标。常用的实现类:ArrayList、LinkedList、Vector。 2:Set: 无序(存入、取出的顺序有可能不一致)、不可重复存储、没有索引下标。常用的实现类:HashSet、LinkedHashSet、TreeSet。 3:Map: 是一个键值对集合,(Key)键 无序、唯一;(Value)值 允许重复。常用的实现类:HashMap、Tr...

qq_42027706的博客 1478

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

java基础--4集合(List|Set|Map)

1、hashmap 1.7 数组+链表 先根据key值计算出hash值以及h值(h值是java实现中处理得到的更优的index索引值) 查找table数组中的h位置,得到相应的键值对链表 根据key值,遍历键值对链表,找到相应的键值对 (时间复杂度O(n)) 从键值对中取出value值 1.8 数组+链表+红黑树 当链表中的元素超过了 8 个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。 Java7 中使用 Entry 来代表每个 HashMap 中的数据节点,

shining曙光的博客 192

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

javaSE学习笔记(五)集合框架-Collection,List,Set,Map,HashMap,Hashtable,ConcurrentHashMap

为何随机增删、查询效率都很高:增删是在链表上完成的,而查询只需扫描部分,则效率高。

给自己的程序生涯留下一点痕迹 874

Java集合类详解:List、Set、Map核心实现与使用场景分析

深入剖析Java集合框架中List、Set、Map主流实现类的底层原理、性能特征与实际选型策略,涵盖ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等核心类。

2302_81148623的博客 340

Java 8集合框架总纲:从Collection到Map的核心原理与实践

数据结构是程序设计的基础,而集合框架则是 Java 对常见数据结构的工业级封装。从数组长度固定的痛点出发,集合框架提供了动态扩容、按内容查找、统一遍历等能力。Java 8 引入 Lambda 表达式与 Stream API,让集合操作从命令式转向声明式,同时为 Map 增加了 computeIfAbsent 等实用方法。理解 Collection 与 Map 两大体系是选型的前提:List 适合有序访问,Set 保证元素唯一,Queue 处理任务调度,Map 管理键值映射。ArrayList 基于动态数组、

weixin_33393017的博客 274

Collection,Map的继承关系结构

Collection

sweatorange的博客 268

java set第n位_Java容器详解

一、容器的概念1. 什么是容器在Java当中,有一个类专门用来存放其它类的对象,这个类就叫做容器,它就是将若干性质相同或相近的类对象组合在一起而形成的一个整体 。2. 常用的Java容器二、List,Map,Set,Queue1. List有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜...

weixin_39762441的博客 273

玩转Java8 Stream,代码效率飞升

概述Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用 Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。特点如下:分类 如上图:具体用法| 流的常用创建方法 使用 Collection 下的 stream() 和 parallelStream() 方法: 使用

欢迎关注公众号:【码农突围】,回复9999,可以获取一份LeetCode刷题笔记 338

java类集框架_Java类集框架

类集框架简介从JDK1.2开始,Java中引入了类集开发框架,所谓的类集指的是一套动态对象数组的实现方案,在实际开发中,没有任何一项开发可以离开数组,但是传统的数组实现起来非常的繁琐,而且长度是其致命伤,正是因为长度问题,所以传统的数组是不可能大范围使用的,但是开发又离不开数组,所以最初就只能依靠一些数据结构来实现动态的数组处理,而其中最为重要的两个结构:链表、树,但是面对这些数据结构的实现,又不...

weixin_39859954的博客 147

什么是java的元数据_每日一面:Java中的集合框架底层数据结构是什么?

面试题编号:1015发送消息“1015”即可获取该面试题详细解答01问题描述 Java中的集合框架底层数据结构是什么?这是一道比较基础的Java集合面试题,主要考察面试者比较全面的Java基础知识功底,需要了解Java中集合和Map的数据结构。02参考回答 CollectionListArraylist:Object数组Vector:Object数组Lin...

weixin_39756445的博客 96

Java8中Stream详细用法大全

一、概述 Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。 特点: 1 不是数据结构,不会保存数据。 2 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)

weixin_41825261的博客 750

java第8章,第8章 java集合 - osc_yfyc0r8g的个人空间 - OSCHINA - 中文开源技术交流社区...

第8章 java集合8.1 java集合概述8.2Collection和Iterator接口8.2.1 使用Lambda表达式遍历集合8.2.2 使用java 8增强的Iterator遍历集合元素8.2.3 使用Lambda表达式遍历Iterator8.2.4 使用foreach循环遍历集合元素8.2.5 使用java 8新增的Predicate操作集合8.2.6 使用java 8新增的Strea...

weixin_39609650的博客 105
上一篇: 常见排序汇总--你都了解吗?
下一篇: MySQL数据库基础(从零到一)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值