集合——Set、List、Map

目录

 1.集合框架—Collection

1.1  Collection

1.1.1  List和Set

1.1.2 集合持有对象的引用

1.1.3  add方法

1.1.4  contains方法

1.1.5  size、clear、isEmpty

1.1.6  addAll、containsAll和removeAll

1.2  Iterator

1.2.1 hasNext、next方法

1.2.2 remove方法

1.2.3 增强型for

1.3  泛型机制

1.3.1 泛型在集合中的应用

 2 集合操作—线性表

2.1 List

2.1.1 ArrayList和LinkedList

2.1.2 get和set

2.1.3 插入、删除和获取

2.1.4 List转换数组

2.1.5 数组转换List

2.2 List排序

2.2.1 Collections.sort方法

2.2.2 Comparable

2.2.3 Comparator

2.3 队列和栈

2.3.1 Queue

2.3.2 Deque

 3 集合操作—Map

3.1 Map接口

3.1.1 Map接口

3.1.2  put()方法

3.1.3 get()方法

3.1.4 containsKey()方法、containsValue()方法、V remove(K k)方法

3.2  HashMap 

3.2.1 Hash表原理

3.2.2 Hashcode方法

3.2.3 重写hashcode方法

3.2.4 装在因子及HashMap优化

3.3 Map的遍历

3.3.1 使用keySet()方法

3.3.2 使用entrySet()方法

3.3.3 遍历所有的value

3.4 有序的Map

3.4.1 LinkedHashMap实现有序Map

4 集合综合表


​​​​​​​

 

 1.集合框架—Collection

1.1  Collection

1.1.1  List和Set

List集合:

List接口继承自Collection,特点是可以放重复元素,并且有序

Collection是所有集合的顶级接口,规定了所有集合都要具备的功能
集合与数组一样,用于保存一组元素,但是实现类众多(有多重不同的数据结构),并且对于元素的操作都封装成了方法,使用便捷。
Collection下面常见的两个分类(子接口)
java.util.List:线性表,特点是可以存放重复元素,并且有序
java.util.Set:不可重复的集合,并且大部分实现类的无序的
判定元素是否重复的标志是看元素自身的equals比较的结果

1.1.2 集合持有对象的引用

集合中存储的都是引用类型元素,并且集合只保存每个

元素对象的引用,而并非将元素对象本身存入集合。

1.1.3  add方法

/*
boolean add(E e)
向当前集合中添加给定元素,元素成功添加后返回true
 */
Collection c = new ArrayList();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);

1.1.4  contains方法

boolean contains(E e)

判断当前集合是否包含给定元素

public class CollectionDemo2 {
    public static void main(String[] args) {

     Collection c = new ArrayList();
        c.add(new Point(1,2));
        c.add(new Point(5,7));
        c.add(new Point(3,6));
        System.out.println(c);

        Point p = new Point(5,7);
       /*
        contains判断包含时是根据元素equals方法判断的
         */
        boolean contains = c.contains(p);
        System.out.println("包含:"+contains);
    }
}

1.1.5  size、clear、isEmpty

/*
int size()
返回当前元素个数
 */
int size = c.size();
System.out.println("大小:"+size);
/*
boolean isEmpty()
判断当前集合是否为空集,当size =0 时,返回false。
 */
boolean isEmpty = c.isEmpty();
System.out.println("是否为空:"+isEmpty);
c.clear();//清空集合
System.out.println(c);
System.out.println("是否为空集:"+c.size());

1.1.6  addAll、containsAll和removeAll

Boolean addAll(collection c)

将给定的集合元素添加到当前集合元素中(对于Set集合而言,重复的元素不能放进来多次)

Boolean containsAll(Collection c)

判断当前集合是否包含集合中的所有元素

 Collection a.removeAll(Collection c);

 删除当前集合中给定元素集合的共有元素

public class CollectionDemo5 {
    public static void main(String[] args) {

    Collection c1 = new ArrayList();
        c1.add("你好");
        c1.add("再见");
        c1.add("欢迎");
        System.out.println("c:"+c1);
        Collection c2 = new HashSet();
        c2.add("山东省");
        c2.add("济南市");
        c2.add("再见");
        System.out.println("c2:"+c2);
        c1.addAll(c2);
        System.out.println(c1);
//        c2.addAll(c1);//c1中的java不能重复添加到c2中
//        System.out.println(c2);
        Collection c3 = new ArrayList();
        c3.add("济南市");
        c3.add("你好");
        System.out.println("c3:"+c3);
        boolean contains = c1.containsAll(c3);
        System.out.println("全包含:"+contains);
        /*
        删除当前集合中给定元素集合的共有元素
         */
        c1.removeAll(c3);
        System.out.println("c1:"+c1);
    }
}

1.2  Iterator

 集合提供了统一的遍历方式,迭代器

 Iterator iterator()

 该方法会返回一个遍历当前集合元素的迭代器

 java.util.Iterator接口

迭代器接口,规定了迭代器遍历集合的相关操作,不同的集合都提供了用于遍历自身元素的迭代器实现类

使用迭代器遍历集合遵循:问,取,删的步骤进行,其中删除元素不是遍历过程中的必要操作

1.2.1 hasNext、next方法

Boolean hasNext()

判断是否还有下一个元素可以遍历(第一遍历时询问的就是第一个,第二次就是询问第二个以此类推)

E next() 获取集合下一个元素

public class IteratorDemo {
    public static void main(String[] args) {


        Collection c = new ArrayList();
        c.add("one");
        c.add("*");
        c.add("two");
        c.add("*");
        c.add("three");
        System.out.println(c);
        Iterator it = c.iterator();
        /*
        Boolean hasNext()
        判断是否还有下一个元素可以遍历(第一遍历时询问的就是第一个,第二次就是询问第二个以此类推)
         */
        while (it.hasNext()){
            /*
            E next()
            获取集合下一个元素
             */
            String  str = (String)it.next();
            System.out.println(str);
            if ("*".equals(str)){
                //迭代器在遍历的过程中不允许通过集合的方法增删元素,否则会抛出异常
//                c.remove(str);
                it.remove();
            }

1.2.2 remove方法

在使用迭代器遍历集合时,不能通过集合的remove方法删除集合元素,否则会抛出并发更改异常。我们可以通过迭代器自身提供的remove()方法来删除通过next()迭代出的元素。

c.remove(str);

迭代器的删除方法是在原集合中删除元素。这里需要注意的是,在调用remove方法前必须通过迭代器的next()方法迭代过元素,那么删除的就是这个元素。并且不能再次调用remove方法,除非再次调用next()后方可再次调用。

1.2.3 增强型for

JDK1.5之后退出一个新特性:增强型for循环。可以让我们用相同的语法遍历集合或数组

新循环遍历集合就是迭代器遍历,编译器会将其改为迭代器遍历。

        注意:不要在遍历过程中通过集合方法增删元素。

语法:

for(元素类型e:集合或数组){

循环体

}

public class NewForDemo {
    public static void main(String[] args) {

String[] arr = {"one","two","three","four","five"};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        //新循环是编译器认可的,编译器在编译时会将其改为传统for循环遍历数组
        for (String str : arr){
            System.out.println(str);
        }
        /*
        泛型 JDK1.5一起推出的一个特性:广泛应用与集合当中,在集合汇总泛型的作用是用来规定集合中的元素类型
         */
        Collection<String > c = new ArrayList<>();
        c.add("one");
        c.add("two");
        c.add("three");
        c.add("four");
        c.add("five");
//        c.add(123);//编译不通过,因为集合定义时规定元素必须是String
        System.out.println(c);
        /*
        新循环遍历集合就是迭代器遍历,编译器会将其改为迭代器遍历。
        注意:不要在遍历过程中通过集合方法增删元素。
         */
        //获取集合元素时不用再使用Object接收了,编译器会在编译时自动加上造型操作
        for (String str : c){
            System.out.println(str);
        }
    }
}

 

1.3  泛型机制

1.3.1 泛型在集合中的应用

Arayus类的定义中,ES中的E为泛型参数,在创建对象时可以将类型作为参数传递,此时, 类定义所有的E将被替换成传入的参数

 2 集合操作—线性表

2.1 List

2.1.1 ArrayList和LinkedList

List接口继承自Collection,特点是可以放重复元素,并且有序

List的常用实现类

java.util.ArraysList:内部使用数组实现,查询速度更好

java.util.LinkedList:内部使用链表实现,增删性能更好

List除了Collection挺高的操作之外,自身还提供了一套基于下标操作的方法。

public class ListDemo1 {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
//        List<String> list = new LinkedList<>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");
        System.out.println(list);
    }
}

JDK8之后集合有退出一中遍历元素的方式:forEach方法,基于lambda表达式遍历

foreach是集合自身大方法,所以如果是一个并发安全的集合,这个办法与其他操作时互斥的,可以保证并发安全。

迭代器遍历集合在多线程并发操作时会有问题:如果我们使用一个并发安全的集合,name该集合自身的方法如:add,remove等是能保证并发安全的 ,但是迭代器遍历互斥,因此存在并发安全问题,原来则需要自行维护互斥关系

public class ForeachDemo {
    public static void main(String[] args) {

Collection<String> c = new ArrayList<>();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");

//        for (String str : c){
//        system.out.println(str);
//        }

        c.forEach(e-> System.out.println(e));
    }
}

2.1.2 get和set

E get (int index)

获取给定下标出对应的元素

//获取集合中第三个元素
String str = list.get(2);
System.out.println(str);
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

E set(int index,E e)

将给定元素设置到指定位置,返回值为该位置原有的元素

set方法也称为替换元素操作

   String old = list.set(2,"3");
System.out.println(list);
System.out.println(old);



      /*
        将list集合反转
         */
        for (int i = 0; i < list.size()/2; i++) {
            //获取正数位置上的元素
            //将其设置到倒数位置上,并返回被置换的元素
            //再将原倒数位置元素(被替换的元素)设置到正数位置上
            list.set(list.size()-i-1, list.set(i,list.get(list.size()-i-1)));
        }

//方法二:
//        Collections.reverse(list);
        //import java.util.Collections:集合的工具类,有很多操作集合的功能,下面是用于反转集合的
        System.out.println(list);
    }
}

结果:

[one, two, three, four, five]
[five, four, three, two, one]

2.1.3 插入、删除和获取

 

E add(int index , String str) 将给定的元素插入指定位置

E remove (int index) 删除并返回指定下标对应的元素

public class ListDemo2 {
    public static void main(String[] args) {

       List<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");
        System.out.println(list);
        /*
        E add(int index , String str)
        将给定的元素插入指定位置
         */
        list.add(2,"3");
        System.out.println(list);
        /*
        E remove(int index)
        删除并返回指定下标对应的元素
         */
        String s = list.remove(3);
        System.out.println(list);
        System.out.println(s);
    }
}

List subList ( int start , int end ) 获取当前List集合中指定范围内的子集

public class ListDemo3 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        System.out.println(list);
        //获取3~7
        List<Integer> subList = list.subList(3,8);
        System.out.println(subList);
        for (int i = 0; i < subList.size(); i++) {
            subList.set(i,subList.get(i)*10);
        }
        System.out.println(subList);
        /*
        对子集的操作就是对原集合对应的操作
         */
        System.out.println(list);
        /*
        删除List集合中的2~8
         */
        list.subList(2,9).clear();
        System.out.println(list);
    }
}

2.1.4 List转换数组

Collection定义了一个方法toArray,可以将当前集合转换为一个数组

public class CollectionToArrayDemo {
    public static void main(String[] args) {

        Collection<String> c = new ArrayList<>();
        c.add("one");
        c.add("two");
        c.add("three");
        c.add("four");
        c.add("five");
        System.out.println(c);
//        Object[] arr = c.toArray();
        String[] arr = c.toArray(new String[c.size()]);
        System.out.println(Arrays.toString(arr));
    }
}

2.1.5 数组转换List

数组的工具类:java.util.Arrays提供了一个静态方法asList,可以将当前数组转换为一个list集合

public class ArrayToListDemo {
    public static void main(String[] args) {

       String[] arr = {"one","two","three","four","five"};
        System.out.println(Arrays.toString(arr));
        List<String> list = Arrays.asList(arr);
        System.out.println(list);
        /*
        数组转换的集合,对其操作就是对源数组对应的操作
         */
        list.set(1,"2");
        System.out.println(list);
        System.out.println(Arrays.toString(arr));
        //由于数组的定长的,因此这个集合不能做增删这样回改变元素个数的操作,会抛出异常
//        list.add("six");
        /*
        所有集合都支持一个参数为Collection的构造方法,在创建当前集合的同时包含给定集合中的所有元素
         */
        List<String> list0 = new ArrayList<>(list);
        System.out.println(list0);
        list0.add("six");
        System.out.println(list0);
    }
}

2.2 List排序

2.2.1 Collections.sort方法

集合的工具类:java.util.Collections提供了一个静态方法sort,可以对List几个进行自然排序(从小到大)

public class SortListDemo {
    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();
        Random ran = new Random();
        for (int i = 0; i < 10; i++) {
            list.add(ran.nextInt(100));
        }
        System.out.println(list);
//        Collections.sort(list);//从小到大
        /*
        JDK8以后,List接口上定义了sort方法,用于排序List集合
         */
        Collections.sort(list,(o1, o2) -> o2-o1);//从大到小
        System.out.println(list);
    }
}

2.2.2 Comparable

 Collections.sort(List list)方法排序集合时会有一个请求:集合元素必须实现接口:

Comparable接口,否则编译不通过

Comparable英文是可比较的意思,因此实现了这个接口的类是可比的,因为必须重写该接口中定义的比较方法,只有元素之间可以比较大小才能进行排序

如果sort方法不能直接应用就不要使用这个方法了,因为它要求元素必须配合实现接口,这就有了侵入性。

侵入性:当我们调用某个功能时,他反过来要求我们为其他地方的,添加额外代码,这就是侵入性,这不利于程序后期的维护

先实现一个point类作为集合元素测试集合相关操作

public class Point implements Comparable{
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public String toString() {
        return "(" + x + "," + y + ')';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x &&
                y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

测试类:

public class SortListDemo {
    public static void main(String[] args) {

List<Point> list = new ArrayList<Point>();
list.add(new Point(1, 2));
list.add(new Point(5, 4));
list.add(new Point(8, 6));
list.add(new Point(7, 8));
list.add(new Point(3, 10));
System.out.println(list);
        Collections.sort(
                list,
                (o1, o2) ->o1.getX()*o1.getX()+o1.getY()*o1.getY()-
                            o2.getX()*o2.getX()-o2.getY()*o2.getY()
                );
        System.out.println(list);
    }
}

2.2.3 Comparator

比较器接口Comparator要求必须重写方法:compare

这个方法的作用是定义两个参数的比较大小规则,返回值为比较结果:

当返回值>0时,表示o1比o2大

当返回值<0时,表示o1比o2小

当返回值=0时,表示o1与o2相对

Collection.sort(List list,comparator c)该方法就是利用传入的比较器将集合中两两元素调用比较compare方法,

 按照比较结果进行从小到大排序的 

       Collections.sort(list);
        Comparator<Point> c = new Comparator<Point>() {
                public int compare(Point o1, Point o2) {
                int olen1 = o1.getX()*o1.getX()+o1.getY()*o1.getY();
               int olen2 = o2.getX()*o2.getX()-o2.getY()*o2.getY();
                return olen1 - olen2;
            }
        };
        Collections.sort(list c);

2.3 队列和栈

2.3.1 Queue

队列 java.util.Queue接口

Queue接口继承自Collection,因此队列一是一个集合,它的实现类可以保存一组元素,但是对于存取元素要求必须遵循先进先出原则

常见实现类:java.util.LinkedList

public class QueueDemo {
    public static void main(String[] args) {

       Queue<String > queue = new LinkedList<>();
        /*
        offer方法是入队操作,将元素添加到队列末尾
         */
        queue.offer("one");
        queue.offer("two");
        queue.offer("three");
        queue.offer("four");
        queue.offer("five");
        System.out.println(queue);
        /*
        E poll()
        出队操作,获取元素后,该元素从队列中被删除
         */
        String str = queue.poll();
        System.out.println(str);
        System.out.println(queue);
        /*
        E peek()
        引出队首元素,获取后元素并不会被删除
         */
        str = queue.peek();
        System.out.println(str);
        System.out.println(queue);
        //可以使用新循环(迭代器)遍历队列,因为队列也是集合,并且遍历后元素仍然在队列中
        for (String s : queue){
            System.out.println(s);
        }
        System.out.println(queue);
        //使用poll方法获取队列所有元素
       while(queue.size()>0){
            System.out.println(queue.poll());
        }
        System.out.println(queue);
    }
}

2.3.2 Deque

 java.util.Deque接口,双端队列

Deque继承自Queue,是队列两端都可以作出入队的队列

实现类:java.util.LinkedList

public class DequeDemo {
    public static void main(String[] args) {

       Deque<String> deque = new LinkedList<>();
        deque.offer("one");
        deque.offer("two");
        deque.offer("three");
        System.out.println(deque);
        deque.offerFirst("four");
        System.out.println(deque);
        deque.offerLast("five");
        System.out.println(deque);
        String str = deque.pollFirst();
        System.out.println(str);
        System.out.println(deque);
        str = deque.pollLast();
        System.out.println(str);
        System.out.println(deque);
    }
}

栈可以保存一组元素,但是存取元素必须遵循先进先出原则,通常使用栈来完成“后退”,“前进”这样的功能。

public class StackDemo {
    public static void main(String[] args) {

       Deque<String> stack = new LinkedList<>();
       stack.push("one");
       stack.push("two");
       stack.push("three");
       stack.push("four");
       stack.push("five");
        System.out.println(stack);
        String str = stack.pop();
        System.out.println(str);
        System.out.println(stack);
        for (String s : stack){
            System.out.println(s);
        }
        System.out.println(stack);
       stack.forEach(e-> System.out.println(e));
        System.out.println(stack);
    }
}

 3 集合操作—Map

3.1 Map接口

3.1.1 Map接口

java.util.map查找表

map体现的样子是一个多行两列的表格,左列称为key,右列称为value。Map总是根据key去获取对应的value。

因此我们可以将查询条件作为key,查询结果作为key,查询结果作为value保存到map中一遍将来查找。

map是一个借口,常用实现类:

java.util.HashMap:散列表,使用散列算法实现的map,当今查询速度碎块的数据结构

java.util.TreeMap:使用二叉树实现的map

3.1.2  put()方法

v put(K k , V v) 将给定元素添加到map中

返回值为被替换的value,注:map有一个要求,key不允许重复,所以适用形同的key存放value时会将原来的value值替换掉

此时put方法就将被替换的value返回,否则返回null。

LinkedHashMap是遍历顺序与put顺序一致的HashMap

3.1.3 get()方法

V get(Object key)
根据给定的key获取对应的value,如果给定的key不存在则返回值为null。

//查看语文的分数
value = map.get("语文");
System.out.println("语文:"+value);
value = map.get("数学");
System.out.println(value);
int size = map.size();
System.out.println("size"+size);

3.1.4 containsKey()方法、containsValue()方法、V remove(K k)方法​​​​​​​

//是否包含给定的key
boolean ck = map.containsKey("数学");
System.out.println("含有数学:"+ck);
//是否包含给定的value
boolean cv = map.containsValue(98);
System.out.println("成绩是否含有98:"+cv);

/*
V remove(K k)
删除给定的key锁对应的这组键值对,返回值为这个key所对应的value
 */
value = map.remove("语文");
System.out.println(map);
System.out.println(value);

3.2  HashMap 

3.2.1 Hash表原理

3.2.2 Hashcode方法

从HashMap的原理中我们可以看到, key的hashCode()方法的返回值对HashMap存储元素时会起着很重要的作用。而hashCode(方法实际上是在Object中定义的。那么应当妥善重写该方法:

对于重写了equals方法的对象般要妥 善的重写继承自Object类的hashCode方法( Object提供的hashCode方法将返回该对象所在内存地址的整数形式)。

重写hashCode方法是需注意两点:其-一、与equals方法的一致性,即equals比较返回true的两个对象其hashCode方法返回值应该相同;其二、hashCode返回的数值应符合hash算法的要求,试想如果有很多对象的hashCode方法返回值都相同,则会大大降低hash表的效率,一般情况下可以使用IDE (如Eclipse )提供的工具自动生成hashCode方法。

3.2.3 重写hashcode方法

public int hashCode() {
Final int prime = 31;
int result = 1;
result= prime*result+age;
result = prime* result + ((gender == nul)? 0 :gender.hashCode();
result = prime * result + ((name == nul) ?0 :name.hashCode());
long temp;
Temp = Double.doubleToLongBits(salary);
result = prime* result + (int) (temp ^ (temp
>>> 32));
return result;
}

3.2.4 装在因子及HashMap优化

Capacity :容量,hash表里bucket(桶)的数量,也就是散列数组大小。

Initial capacity :初始容量,创建hash表时,初始bucket的数量,默认构建容量是16.也可以使用特定容量。

Size :大小,当前散列表中存储数据的数量。

Load factor :加载因子,默认值0.75(就是75%),当向散列表增加数据时如果size/capacity的值大于Loadfactor则发生扩容并且重新散列(rehash)。

性能优化:加载因子较小时,散列查找性能会提高,同时也浪费了散列桶空间容量。0.75是性能和空间相对平衡结果。在创建散列表时指定合理容量,减少rehash提高性能。

3.3 Map的遍历

map支持三种遍历方式:

1:遍历所有key

2:遍历每一组键值对

3:遍历所有value

3.3.1 使用keySet()方法

遍历所有的key

Set keySet()

将当前Map中所有的key以一个Set集合的形式返回,遍历这个Set集合等于便利了所有的key

Set<String> keySet = map.keySet();
for (String key : keySet){
    System.out.println("key:"+key);
}

3.3.2 使用entrySet()方法

遍历每一组键值对

Set(Entry) entrySet()

该方法会将map中每一组键值对以一个Entry实例形式保存到一个Set集合后返回

java.util.Map.Entry

Entry的每个实例表示Map中的每一组键值对,有两个常用方法:getKey和getValue

Set<Map.Entry<String, Integer>> entry = map.entrySet();
for (Map.Entry<String,Integer> e :entry){
    String key = e.getKey();
    Integer value = e.getValue();
    System.out.println(key+" 分数是:"+value);
}

3.3.3 遍历所有的value

Collection<Integer> values = map.values();
for (Integer value : values){
    System.out.println("value:"+value);
}

3.4 有序的Map

3.4.1 LinkedHashMap实现有序Map

使用Map接扣的哈希表和链表实现,具有可预知的迭代顺序。

此实现与HashMap的不同之处在于:LinkedHashMap维护着一个双向循环链表。 此链表定义了迭代顺序,该迭代顺序通常就是存放元素的顺序。需要注意的是,如果在Map中重新存入已有的key ,那么key的位置不会发生改变,只是将value值替换。

4 集合综合表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Healer_小振

感谢大佬的支持和鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值