list集合 & Set集合 & 泛型 & 集合排序

集合框架概念

集合,用来保存一组数据的数据结构。java.util 包中包含了 Java 最强大的子系统之一,这就是“集合框架”。 “集合框架”是在 Java2 初始版本中增加进来的,Java SE 1.4 和 5.0 中增强了它的功能。一个集合就是一组对象的容器。集合的加入导致了 java.util 中许多元素在构造和体系结构方面的根本变化,它也扩展了能够应用的任务域。所以说,集合是所有 Java 程序员都需要密切关注并熟练掌握的一种技术。 Java 的集合框架使我们的程序处理对象的方式更加标准化。Java2 之前,Java 提供了一批容器类来存储和操作对象组。尽管这些类很有用,但它们缺乏一个中心 的、统一的主题。同时, 以前的方法没有设计为容易扩展的、适应性强的形式,而集合解决了这些问题。 集合框架被设计用于达到几个目的:首先,这种框架必须是高性能的;其次, 框架必须允许不同类型的集合以相似的方式进行操作并且有高度的互用性;再次, 扩展和改变一个集合也必须是很容易的。为了实现这一目标,整个集合框架被设计为一系列标准的接口,可以使用这些接口的几个标准实现。如果愿
意,也可以实现自己的集合处理类。最后,增加了允许集成标准数组到集合结构的机制。

9.2 集合框架体系图

在这里插入图片描述

9.3 集合框架中常用集合类的继承关系图

在这里插入图片描述

9.4 list集合

List 接口扩展 Collection 接口并声明集合的行为是存储一个序列的元素,默认按照添加到集合的顺序存放元素。支持下标访问,下标从 0 开始,可以把元素插入到列表中或者对列表中的元素进行访问。
List结构图:

在这里插入图片描述
9.4.1 List接口的具体实现类ArrayList

ArrayList 又叫做可变长度数组, 长度是变化的,访问的位置不能超出存储数量。List 接口的大小可变数组的实现。实现了所有可选列表操作,**并允许包括 null 在内的所有元素。**除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。

ArrayList中常用的方法:

1.add(E e)
方法作用:将指定的元素添加到此列表的尾部。
方法参数:基本数据类型、引用数据类型
方法返回值:boolean类型

2.add(int index, E element)
方法作用:将指定的元素插入此列表中的指定位置。
方法参数:第一个参数为正整数,第二个参数为基本数据类型、引用数据类型;
方法返回值:void

3.addAll(Collection<? extends E> c)
方法作用:按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
方法参数:Collection类型的集合(List、Set)
方法返回值:boolean类型

4.addAll(int index, Collection<? extends E> c)
方法作用:从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
方法参数:第一个参数为正整数参数;第二个参数为Collection类型的集合(List、Set);
方法返回值:boolean类型

5.clear()
方法作用:移除此列表中的所有元素。
方法参数:无
方法返回值:void

6.contains(E e)
方法作用:判断列表中是否包含指定元素
方法参数:基本数据类型、引用数据类型
方法返回值:boolean类型;如果存在返回true

7.get(int index)
方法作用:返回此列表中指定位置上的元素。
方法参数:正整数参数;
方法返回值:列表指定下标的元素

8.indexOf(E e)
方法作用: 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
方法参数:基本数据类型、引用数据类型
方法返回值:int类型的值

9.isEmpty()
方法作用:判断列表是否为空
方法参数:无
方法返回值:boolean类型的值;如果此列表中没有元素,则返回 true

10.lastIndexOf(Object o)
方法作用: 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
方法参数:基本数据类型、引用数据类型
方法返回值:int类型的值

11.remove(int index)
方法作用:移除此列表中指定位置上的元素。
方法参数:正整数类型参数,如果参数索引超出范围 (index < 0 || index >= size()),那么会抛出IndexOutOfBoundsException下标越界异常
方法返回值:从列表中移除的元素

12.remove(Object o)
方法作用: 移除此列表中首次出现的指定元素(如果存在)。
方法参数: 引用数据类型
方法返回值:boolean类型值

13.set(int index, E element)
方法作用: 用指定的元素替代此列表中指定位置上的元素。
方法参数: index - 要替代的元素的索引;element - 存储在指定位置上的元素
方法返回值:以前位于该指定位置上的元素

14.size()
方法作用:返回此列表中的元素数。
方法参数:无
方法返回值:int类型

15.toArray()
方法作用: 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
方法参数:无
方法返回值: Object[],Object类型数组,如果集合是泛型,那么返回指定类型的数组;

示例(封装类):

package com.ambow.test;
public class Student {
	private int id;//表示学生学号
	private String name;//表示学生姓名
	private String sex;//表示学生性别
	private int age;//表示学生年龄
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}	
}

示例(无泛型):

package com.ambow.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * List集合是有序存储的,可以存储重复元素
 * @author sqs
 *
 */
public class ListDemo1 {
	public void test(){
		//泛型:规定集合存储的类型
		//如果没有规定集合的泛型,那集合默认存储的类型为Object,因为Object是所有类的父类,所以也就是说
		//该集合可以存储任何类型的数据
		//使用多态的形式创建ArrayList的实例
		List list=new ArrayList();
		Student stu=null;
		for(int i=0;i<5;i++){
			stu=new Student();
			stu.setId(1+i);//1
			stu.setName("尼古拉斯赵四"+i);//尼古拉斯赵四0
			stu.setSex("男");//男
			stu.setAge(34+i);//34
			//向集合中添加元素
			list.add(stu);
		}
		//list.size()表示集合的大小
		System.out.println("集合的大小:"+list.size());
		
		Student stu2=new Student();
		stu2.setId(5);
		stu2.setName("尼古拉斯赵四4");
		stu2.setSex("男");
		stu2.setAge(38);
		list.add(stu2);
		
		list.add("Student对象");
		//遍历集合的三种方式:普通for循环,增强for循环,迭代器
		
		//使用普通for循环遍历List集合
		for(int i=0;i<list.size();i++){
			//因为没规定泛型,所以集合存储的类型为Object,那取出来的元素也是Object类型
			//从集合中取元素
			Object o=list.get(i);
			//要把Object类型转为Student类型需要进行强转
			Student stu1=(Student) o;
			System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
			System.out.println("=====================================================");
		}
		System.out.println("---------------------------------------------------------------");
		//使用增强for循环来遍历List集合
		for(Object o:list){
			Student stu1=(Student) o;
System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
			System.out.println("==========================================");
		}
		System.out.println("---------------------------------------------------------------");
		//使用迭代器来遍历List集合
/*
		 * 使用迭代器步骤:1.将集合放入迭代器中iterator() 
		 * 		2.利用while循环来调用方法判断有没有下一个元素hasNext()
		 * 		3.判断的结果如果为true,将当前元素遍历出来.next()
		 * */
		Iterator iter=list.iterator();
		//iter.hasNext()判断迭代器中有没有下一个元素,如果有将该元素遍历出来,没有循环终止
		while(iter.hasNext()){
			//将该元素遍历出来
			Object o=iter.next();
			Student stu1=(Student) o;
			System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
			System.out.println("====================================================");
		}
	}
	public static void main(String[] args) {
		ListDemo1 ld1=new ListDemo1();
		ld1.test();
	}
}

示例(有泛型):

package com.ambow.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * 有泛型的List集合
 * @author sqs
 *
 */
public class ListDemo2 {
	public static void main(String[] args) {
		//一旦规定了泛型,那该集合只能存储该泛型类型的数据
		//当前集合的泛型为Student,所以该集合只能存储Student类型的元素,也就是Student的对象
		List<Student> list=new ArrayList<Student>();
		Student stu=null;
		for(int i=0;i<5;i++){
			stu=new Student();
			stu.setId(1+i);//1
			stu.setName("尼古拉斯赵四"+i);//尼古拉斯赵四0
			stu.setSex("男");//男
			stu.setAge(34+i);//34
			//向集合中添加元素
			list.add(stu);
		}
		//移除集合中的元素
		list.remove(3);
		
		Student stu2=new Student();
		stu2.setId(4);//1
		stu2.setName("尼古拉斯赵四"+3);//尼古拉斯赵四0
		stu2.setSex("男");//男
		stu2.setAge(37);//34
		//向指定位置处添加元素
		list.add(3, stu2);
		list.add(stu2);
		//将指定集合中所有元素全部移除
//		list.removeAll(list);
		//遍历List集合的三种方式:普通for循环,增强for循环,迭代器
		
		//使用普通for循环
		System.out.println("============================使用普通for循环==========================");
		for(int i=0;i<list.size();i++){
			//使用List集合中的get方法来获取集合中的元素
			Student stu1=list.get(i);
			System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
		}
		//使用增强for循环
		System.out.println("============================使用增强for循环==========================");
		for(Student stu1:list){
			System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
		}
		//使用迭代器
		System.out.println("============================使用迭代器==========================");
		Iterator<Student> iter=list.iterator();
		while(iter.hasNext()){
			Student stu1=iter.next();
			System.out.println(stu1.getId()+"\t"+stu1.getName()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
		}
	}
}

9.4.2 List接口的具体实现类Vector

Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
示例:

package com.ambow.test;
import java.util.List;
import java.util.Vector;
import com.ambow.test.Student;
public class ListDemo {
	public static void main(String[] args) {
		//使用Vector与使用ArrayList实现类在添加元素,及遍历元素等操作
		//都是相同的
		List<Student> list=new Vector<>();
		Student stu=null;
		for(int i=0;i<5;i++){
			stu=new Student();
			stu.setId(1+i);//1
			stu.setName("尼古拉斯赵四"+i);//尼古拉斯赵四0
			stu.setSex("男");//男
			stu.setAge(34+i);//34
			//向集合中添加元素
			list.add(stu);
		}
	}
}

9.4.3 ArrayList与Vector的区别

在这里插入图片描述

9.4.4 List接口的具体实现类LinkedList

LinkedList底层使用的链表数据结构。采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引特点:增删很快,查询慢。
示例:

package com.ambow.test;
import java.util.LinkedList;
import java.util.List;
import com.ambow.test.Student;
public class ListDemo {
	public static void main(String[] args) {
		//使用LinkedList实现类与使用ArrayList实现类在添加元素,及遍历元素等操作
		//都是相同的
		List<Student> list1=new LinkedList<>();
		Student stu1=null;
		for(int i=0;i<5;i++){
			stu1=new Student();
			stu1.setId(1+i);//1
			stu1.setName("尼古拉斯赵四"+i);//尼古拉斯赵四0
			stu1.setSex("男");//男
			stu1.setAge(34+i);//34
			//向集合中添加元素
			list1.add(stu1);
		}
	}
}

9.4.5 LinkedList 和ArrayList区别?

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

9.5 Set集合

Set 结构定义了一个集合,它扩展了 Collection 接口。特点是元素在集合中无序存储,不允许存在相同的元素,因此,如果试图插入相同元素到此集合中, add 方法将返回 false。每个元素都必须定义 equals()方法以判断所谓的独一性。
Set结构图:

在这里插入图片描述

9.5.1 Set接口具体实现类HashSet

HashSet使用的是相当复杂的方式来存储元素的,使用HashSet能够最快的获取集合中的元素,效率非常高(以空间换时间)。会根据hashcode和equals来判断是否是同一个对象,如果hashcode一样,并且equals返回true,则是同一个对象,不能重复存放。

HashSet的常用方法:
1.add(E e) 如果此 set 中尚未包含指定元素,则添加指定元素。
2.clear() 从此 set 中移除所有元素。
3.contains(Object o) 如果此 set 包含指定元素,则返回 true。
4.isEmpty() 如果此 set 不包含任何元素,则返回 true。
5.remove(Object o) 如果指定元素存在于此 set 中,则将其移除。
6.size() 返回此 set 中的元素的数量
7.iterator() 返回对此 set 中元素进行迭代的迭代器。

示例(封装类):

package com.ambow.test;
public class Student {
	private int id;//表示学生学号
	private String name;//表示学生姓名
	private String sex;//表示学生性别
	private int age;//表示学生年龄
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

示例(具体实现):

package com.ambow.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
 * Set集合中不允许出现重复元素
 * 使用HashSet实现类创建的集合是无序存储的
 * @author sqs
 *
 */
public class SetDemo1 {
	public static void main(String[] args) {
		//使用多态的方式创建HashSet实现类的对象,也就是名为set的Set集合
		Set<Student> set=new HashSet<>();
		Student stu=new Student();
		stu.setId(5);
		stu.setName("刘能");
		stu.setSex("女");
		stu.setAge(48);
		//向Set集合中添加元素也是使用add方法
		set.add(stu);
		set.add(stu);
		Student stu1=null;
		for(int i=1;i<5;i++){
			stu1=new Student();
			stu1.setId(i);
			stu1.setName("刘能"+i);
			stu1.setSex("男");
			stu1.setAge(32+i);
			
			set.add(stu1);
		}
		//因为Set集合是无序存储的,所有没有get(int index)方法,不能使用普通for循环来遍历
		//遍历Set集合的两种方式:增强for循环,迭代器
		//使用增强for循环来遍历Set集合
		System.out.println("================================使用增强for循环来遍历Set集合==================================");
		for(Student stu2:set){
			System.out.println(stu2.getId()+"\t"+stu2.getName()+"\t"+stu2.getSex()+"\t"+stu2.getAge());
		}
		
		//使用迭代器来遍历Set集合
		System.out.println("================================使用迭代器来遍历Set集合==================================");
		Iterator<Student> iter=set.iterator();
		while(iter.hasNext()){
			Student stu2=iter.next();
			System.out.println(stu2.getId()+"\t"+stu2.getName()+"\t"+stu2.getSex()+"\t"+stu2.getAge());
		}
	}
}

9.5.2 Set接口具体实现类TreeSet

**Tree Set 类的底层结构为树的一种有序的 Set。对象以升序顺序存储,访问和遍历它的时间很快,**这使得 Tree Set 成为存储大量必须能很快查找的排序信息的很好选择。我们还可以自 Set 中获取出一个带次序性的序列,这里不做具体的说明。

9.5.3 Set接口具体实现类LinkedHashSet

LinkedHashSet按照插入顺序保存对象,同时还保存了HashSet的查询速度
示例:

package com.ambow.test;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import com.lechenggu.demo.Student;
/**
 * Set集合中不允许出现重复元素
 * 使用LinkedHashSet实现类创建的集合是有序存储的
 * @author sqs
 *
 */
public class SetDemo {
	public static void main(String[] args) {
		Set<Student> set=new LinkedHashSet<>();
		Student stu1=null;
		for(int i=1;i<6;i++){
			stu1=new Student();
			stu1.setId(i);
			stu1.setName("刘能"+i);
			stu1.setSex("男");
			stu1.setAge(32+i);
			//向Set集合中添加元素
			set.add(stu1);
		}
		//因为Set集合是无序存储的,所有没有get(int index)方法,不能使用普通for循环来遍历
		//遍历Set集合的两种方式:增强for循环,迭代器
		//使用增强for循环来遍历Set集合
		System.out.println("================================使用增强for循环来遍历Set集合==================================");
		for(Student stu2:set){
			System.out.println(stu2.getId()+"\t"+stu2.getName()+"\t"+stu2.getSex()+"\t"+stu2.getAge());
		}
		
		//使用迭代器来遍历Set集合
		System.out.println("================================使用迭代器来遍历Set集合==================================");
		Iterator<Student> iter=set.iterator();
		while(iter.hasNext()){
			Student stu2=iter.next();
			System.out.println(stu2.getId()+"\t"+stu2.getName()+"\t"+stu2.getSex()+"\t"+stu2.getAge());
		}
	}
}

9.8 泛型

泛型本质上就是为类提供"类型参数",它们也被称为参数化类型或参量多态。

为什么要用泛型?
程序运行过程中要存储的对象数量未定、类型未定。普通数组无法满足我们的要求,需要我们写一个类完成这样的需求。其中集合框架中对泛型的应用非常广泛。
使用泛型的注意事项:
1.类型参数不能实例化。例如使用形如 T t= new T()会出现编译错误。
2.不能实例化类型参数的数组。例如使用形如 T[] ts= new T[10]会出现编 译错误。
3.类的静态变量不能声明为类型参数类型。例如使用形如 private static T t 会出现编译错误。
4.泛型类不能继承自 Throwable 以及其子类。例如形如 public class GenExpection extends Exception{}会出现编译错误。

说明:关于泛型的示例我们在list集合中已经讲解。

9.9 集合排序

Java API针对集合类型排序提供了两种支持:

1>java.util.Collections.sort(java.util.List)
要求所排序的元素类必须实现java.lang.Comparable接口。
2>java.util.Collections.sort(java.util.List, java.util.Comparator)
要求实现一个java.util.Comparator接口。

Comparable介绍:

Comparable是在集合内部定义的方法实现的排序,位于java.lang下。
Comparable 接口仅仅只包括一个函数,Comparable是一个对象,本身就已经支持自比较所需要实现的接口。
自定义类要在加入list容器中后能够排序,也可以实现Comparable接口。

在用Collections类的sort方法排序时若不指定Comparator,那就以自然顺序排序。所谓自然顺序就是实现Comparable接口设定的排序方式。
若一个类实现了comparable接口,则意味着该类支持排序。
如String、Integer自己就实现了Comparable接口,可完成比较大小操作。

一个已经实现comparable的类的对象或数据,可以通过Collections.sort(list) 或者Arrays.sort(arr)实现排序。通过Collections.sort(list,Collections.reverseOrder());对list进行倒序排列。

Comparator介绍:

Comparator是在集合外部实现的排序,位于java.util下。

Comparator接口包含了两个函数。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以新建一个该类的比较器来进行排序。这个比较器只需要实现comparator即可。
如果引用的为第三方jar包,这时候,没办法改变类本身,可是使用这种方式。
Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。

Comparator体现了一种策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
comparable相当于内部比较器。comparator相当于外部比较器。

List排序:

List数组排序和普通数组的排序又不一样了。其实Java针对数组和List的排序都有实现,对数组而言,你可以直接使用Arrays.sort,对于List和Vector而言,你可以使用Collections.sort方法。
示例:

public class Player implements Comparable<Player>{  
 	//实现接口方法,将来排序的时候sort看正负数还是零来进行判断大小   
       	@Override  
       	public int compare To(Player player){  
            		return this.get Age() - player.get Age();  
       	}  
}

Set排序:

Java对于Set有按照自然顺序排列的实现类——TreeSet,对这个TreeSet对象的引用进行操作就行了,自己就是排好序的。当然,TreeSet也提供了多个构造方法,尤其是接收Comparator类型参数的构造方法,允许开发者按照自己的想法进行排序,而不仅是局限于自然排序。
示例:

public class Attendance implements Comparable {
	//实现接口
	@Override 
 	public int compare To(Object o) {
  		Attendance a=(Attendance)o;
  		return this.Attica.attic;
 	}
}

Map排序:
Map是键值对,所以既可以按照键进行排序,也可以按照值进行排序。通常因为键不能同,但是值可以同,所以很多都是用值来进行排序。

思路:Map遍历的时候要使用Map.Entry,那么你可以使用map.entrySet()获取一个set对象,里面都是Map.Entry,排序的时候最好是将这个set装到一个list里面去,然后定义一个Comparator对象,在里面实现compare方法,返回一个差值,然后使用Collections.sort方法,将list对象和comparator对象传进去,排序就完成了。
示例:

         Map<String, Player> map = new Hash<String, Player>();  
         Player p1 = new Player("John", 1000);  
         Player p2 = new Player("Ben", 3000);  
         Player p3 = new Player("Jack", 2000);  
         map.put(p1);  
         map.put(p2);  
         map.put(p3);  
//将Map里面的所以元素取出来先变成一个set,然后将这个set装到一个list里面  
List<Map.Entry<String, Player>> list = new Array<Map.Entry<String, Player>>(map.entropy()); 
//定义一个Comparable  
Comparable<Map.Entry<String, Player>> Comparable = new Comparable<Map.Entry<String, Player>>(){  
     @Override  
      public int compare(Entry<String, Player> p1, Entry<String, Player> p2){  
      //之所以使用减号,是想要按照分数从高到低来排列  
      return -(p1.get Value().score - p2.get Value().score);  
   }  
      };  
//进行排序
       Collections.sort(list, Comparable);  
       for(Map.Entry<String, Player> entry:list){  
          System.out.print(entry.get Value().name + ":" + entry.get Value().score);  
     }

排序结果:
Ben:3000
Jack:2000
John:1000

三种排序总结:

所有的集合排序最后都可以转换为List的排序,因为Collections本身提供了对List排序的支持。其中Map可以变为set,set可以变为list,所以都可以变为list。

1.对于最简单的情况,就是要被排序的类实现一个Comparable接口,然后实现compare方法,按照自然的方式进行减运算,返回减运算的结果,然后直接使用Collections.sort(List list)方法就行了。这一种叫做自然排序,只适合原始的List和Set。

2.如果你不想使用自然排序,没问题,那么就定义一个Comparator对象,将逻辑在那里面去实现,然后使用Collections.sort(List list, Comparator comparator)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值