Java -- 算法中用到的java基础知识

1.创建数组

接触到的语言太多了,都忘了java的数组创建语法了。

	
	(1) int []a = new int[6];     //数组中的初值为0
	
	(2) int []a = new int[6];      //直接在定义时初始化
	
    (3) int []a = {1,2,3,4,5,6};  //直接来

二维数组

 //第一种方式:
        int a[][]={{1,2,3},{4,5,6}};
        //第二种方式;
        int[][] ints = new int[4][2];
        ints[i][j] =__; //分别赋值
        //第三种方式:第二维的长度可以动态申请
        int[][] arr3 = new int[5][];//五行的长度
        for(int i=0; i<arr3.length; ++i){
            arr3[i]=new int[i+1];   //列的长度每次都变化。每次都要重新申请空间(长度)
            for(int j=0; j<arr3[i].length; ++j)
                arr3[i][j]= i+j;

2.容器概念(摘自:链接

容器确实是java中相当重要的一环,挑选合适的容器进行编码绝对是算法的根本。
如图所示,其中淡绿色的表示接口,红色的表示经常使用的类。

在这里插入图片描述

java中的容器旨在保存对象,类型上可以分两类:

Collection:
一个独立元素的序列,这些元素都服从一条或多条规则。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)

Map:
一组成对的***值键对***对象,允许用键来查找值。ArrayList允许我们用数字来查找值,它是将数字和对象联系在一起。而Map允许我们使用一个对象来查找某个对象,它也被称为***关联数组***。或者叫做***字典***。

先说 Collection, 其中的List有两个实现类,ArrayList和LinkList,这两个的区别就是数组和链表的区别,前者善查找,不便插入删除。后者正好相反。

Set 则是一个 不能存在重复对象的集合。所以Set最常用的就是测试归属性,很容易的询问出某个对象是否存在Set中。并且Set是具有和Collection完全一样的接口,没有额外的功能,只是表现的行为不同。Set下面还有两个实现类,HashSet和TreeSet,***HashSet***查询速度比较快,但是存储的元素是随机的并没有排序。***TreeSet***是将元素存储红-黑树结构中,所以存储的结果是有顺序的(所以如果你想要自己存储的集合有顺序那么选择TreeSet)。

HashSet和TreeSet 区别:
1、TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例。

Queue是队列,队列是典型的先进先出的容器,就是从容器的一端放入元素,从另一端取出,并且元素放入容器的顺序和取出的顺序是相同的。LinkedList提供了对Queue的实现,LinkedList向上转型为Queue。其中Queue有offer、peek、element、pool、remove等方法

offer是将元素插入队尾,返回false表示添加失败。peek和element都将在不移除的情况下返回对头,但是peek在对头为null的时候返回null,而element会抛出NoSuchElementException异常。poll和remove方法将移除并返回对头,但是poll在队列为null,而remove会抛出NoSuchElementException异常。

PriorityQueue,这个时候如果在调用offer方法插入一个对象的时候,这个对象就会按照优先级在对列中进行排序,默认的情况是自然排序,当然我们可以通过Comparator来修改这个顺。PriorityQueue可以确保当你调用peek、pool、remove方法时,获取的元素将是对列中优先级最高的元素。通过代码查看

public static void main(String[] args) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
        Random rand = new Random();
        for (int i = 0; i < 10; i++) {
            priorityQueue.offer(rand.nextInt(i + 10));
        }
        QueueDemo.printQ(priorityQueue);
        List<Integer>ints= Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25);
        priorityQueue=new PriorityQueue<Integer>(ints);
        QueueDemo.printQ(priorityQueue);
    }

Map
Map在实际开发中使用非常广,特别是HashMap,想象一下我们要保存一个对象中某些元素的值,如果我们在创建一个对象显得有点麻烦,这个时候我们就可以用上map了,HashMap采用是散列函数所以查询的效率是比较高的,如果我们需要一个有序的我们就可以考虑使用TreeMap。这里主要介绍一下HashMap的方法,大家注意***HashMap的键可以是null***,而且***键值不可以重复***,如果重复了以后就会对第一个进行键值进行覆盖。

put进行添加值键对,containsKey验证键是否存在、containsValue验证值是否存在、keySet获取所有的键集合、values获取所有值集合、entrySet获取键值对。

总结:

1):数组是将数字和对象联系起来,它保存明确的对象,查询对象时候不需要对查询结果进行转换,它可以是多维的,可以保存基本类型的数据,但是数组一旦生成,其容量不能改变。所以数组是不可以直接删除和添加元素。

2):Collection保存单一的元素,而Map保存相关联的值键对,有了Java泛型,可以指定容器存放对象类型,不会将错误类型的对象放在容器中,取元素时候也不需要转型。而且Collection和Map都可以自动调整其尺寸。容器不可以持有基本类型。

3):像数组一样,List也建立数字索性和对象的关联,因此,数组和List都是排好序的容器,List可以自动扩容

4):如果需要大量的随机访问就要使用ArrayList,如果要经常从中间插入和删除就要使用LinkedList。

5):各种Queue和Stack由LinkedList支持

6):Map是一种将对象(而非数字)与对象相关联的设计。HashMap用于快速访问,TreeMap保持键始终处于排序状态,所以不如HashMap快,而LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问的能力

7):Set不接受重复的元素,HashSet提供最快的访问能力,TreeSet保持元素排序状态,LinkedHashSet以插入顺序保存元素。

3.容器操作

Collection:

Collection<Integer> collection=new ArrayList<Integer>();
Collections.addAll(collection, 4,5,6);//后面接受一个数组,这个方法快
collection.addAll(Arrays.asList(4,5,6));
collection.remove(Object or index); 调用一次方法只能删除第一个

List

public class ListDemo {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("a");// 向集合中追加元素
        list.add(1, "b");// 向集合的制定位置中追加元素
        list.addAll(list);// 向集合追加一个collection,只可追加collection,由于java不提供collection的实现,由它的下级接口来实现
        list.addAll(4, list);// 与上述含义相同, “4”意为追加元素所放的位置
        int i = list.size();// 长度
        System.out.println(i);
        list.get(0);// 根据元素下标来取集合中的元素
        list.remove(7);// 根据集合中元素下标位置来删除元素
        // 此方法是用来比较的,与equals比较相似,现在list的元素中有[a, b, a, b, a, b, a],来和"a,b,c"比较会返回false,
        // 但是注意再用来比较String字符串的时候会进行局部的比较,两组字符串部分相同的情况下会返回true
        list.contains("a,b,c");
        //为了将List转为数组,JDK提供了toArray
        //实现方式一:
        String [] array=(String[]) list.toArray(new String[list.size()]);
        for(String arrays: array) {
            System.out.println(arrays);
        }
        //方式二:
        String [] arr=new String [list.size()];
        list.toArray(arr);
        for(String arrs: arr) {
            System.out.println(arrs);
        }
        //在集合中判断是否为空 ,不空返回false,空会返回true,常常会与null!=list来共同判定集合是否为空,
        //null!=list和list.isempty最大的区别是:一个人要喝水,前者判断是否有水杯,后者判断的是水杯是否有水
        System.out.println(list.isEmpty());//false
        System.out.println(null!=list);//true
        //该方法去比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,
        //则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。
        //这里会涉及到hashcode相关内容,我会单独开一篇来介绍
        list.equals(arr);//false
        //在集合中查找元素 ,"a"如果有 ,返回所查找元素的下标,如果不存在则返回-1
        list.indexOf("a");
        //打印集合元素
        //方式一:
        Iterator it=list.iterator();
        while(it.hasNext()) {
            String string=(String) it.next();
            System.out.println(string);
        }
        //方式二:
        for (Object o:list) {
            System.out.println(o);
        }
        //方式三:
        for(int s=0;s<list.size();s++) {
            System.out.println(list.get(s));
        }
        //将list释放,元素清空,且无返回值
        list.clear();
        System.out.println(list);

        
    }
}

Stack
Vector

在这里插入图片描述

Queue

import java.util.LinkedList;
import java.util.Queue;
 
public class Main {
    public static void main(String[] args) {
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
    }
}

add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
  remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
  element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
  offer 添加一个元素并返回true 如果队列已满,则返回false
  poll 移除并返问队列头部的元素 如果队列为空,则返回null
  peek 返回队列头部的元素 如果队列为空,则返回null
  put 添加一个元素 如果队列满,则阻塞
  take 移除并返回队列头部的元素 如果队列为空,则阻塞

Map

equals(Object o) 比较指定对象与此 Map 的等价性
hashCode() 返回此 Map 的哈希码
clear() 从 Map 中删除所有映射
remove(Object key) 从 Map 中删除键和关联的值
put(Object key, Object value) 将指定值与指定键相关联
clear() 从 Map 中删除所有映射
putAll(Map t) 将指定 Map 中的所有映射复制到此 map
尽管您可能注意到,纵然假设忽略构建一个需要传递给 putAll() 的 Map 的开销,使用 putAll() 通常也并不比使用大量的 put() 调用更有效率,但 putAll() 的存在一点也不稀奇。 这是因为,putAll() 除了迭代 put() 所执行的将每个键值对添加到 Map 的算法以外,还需要迭代所传递的 Map 的元素。 但应注意,putAll() 在添加所有元素之前可以正确调整 Map 的大小,因此如果您未亲自调整 Map 的大小(我们将对此进行简单介绍),则 putAll() 可能比预期的更有效。

查看 Map

迭代 Map 中的元素不存在直接了当的方法。 如果要查询某个 Map 以了解其哪些元素满足特定查询,或如果要迭代其所有元素(无论原因如何),则您首先需要获取该 Map 的“视图”。 有三种可能的视图(参见表 3)

所有键值对 — 参见 entrySet()
所有键 — 参见 keySet()
所有值 — 参见 values()

前两个视图均返回 Set 对象,第三个视图返回 Collection 对象。 就这两种情况而言,问题到这里并没有结束,这是因为您无法直接迭代 Collection 对象或 Set 对象。要进行迭代,您必须获得一个 Iterator 对象。 因此,要迭代 Map 的元素,必须进行比较烦琐的编码

值得注意的是,这些对象(Set、Collection 和 Iterator)实际上是基础 Map 的视图,而不是包含所有元素的副本。 这使它们的使用效率很高。 另一方面,Collection 或 Set 对象的 toArray() 方法却创建包含 Map 所有元素的数组对象,因此除了确实需要使用数组中元素的情形外,其效率并不高。

我运行了一个小测试(随附文件中的 Test1),该测试使用了 HashMap,并使用以下两种方法对迭代 Map 元素的开销进行了比较:

此测试使用了两种测量方法: 一种是测量迭代元素的时间,另一种测量使用 toArray 调用创建数组的其他开销。 第一种方法(忽略创建数组所需的时间)表明,使用已从 toArray 调用中创建的数组迭代元素的速度要比使用 Iterator 的速度大约快 30%-60%。 但如果将使用 toArray 方法创建数组的开销包含在内,则使用 Iterator 实际上要快 10%-20%。 因此,如果由于某种原因要创建一个集合元素的数组而非迭代这些元素,则应使用该数组迭代元素。 但如果您不需要此中间数组,则不要创建它,而是使用 Iterator 迭代元素。

表 3: 返回视图的 Map 方法: 使用这些方法返回的对象,您可以遍历 Map 的元素,还可以删除 Map 中的元素。

entrySet() 返回 Map 中所包含映射的 Set 视图。 Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
keySet() 返回 Map 中所包含键的 Set 视图。 删除 Set 中的元素还将删除 Map 中相应的映射(键和值)
values() 返回 map 中所包含值的 Collection 视图。 删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)

访问元素

表 4 中列出了 Map 访问方法。Map 通常适合按键(而非按值)进行访问。 Map 定义中没有规定这肯定是真的,但通常您可以期望这是真的。 例如,您可以期望 containsKey() 方法与 get() 方法一样快。 另一方面,containsValue() 方法很可能需要扫描 Map 中的值,因此它的速度可能比较慢。

表 4: Map 访问和测试方法: 这些方法检索有关 Map 内容的信息但不更改 Map 内容。

get(Object key) 返回与指定键关联的值
containsKey(Object key) 如果 Map 包含指定键的映射,则返回 true
containsValue(Object value) 如果此 Map 将一个或多个键映射到指定值,则返回 true
isEmpty() 如果 Map 不包含键-值映射,则返回 true
size() 返回 Map 中的键-值映射的数目

对使用 containsKey() 和 containsValue() 遍历 HashMap 中所有元素所需时间的测试表明,containsValue() 所需的时间要长很多。 实际上要长几个数量级! (参见图 1 和图 2,以及随附文件中的 Test2)。 因此,如果 containsValue() 是应用程序中的性能问题,它将很快显现出来,并可以通过监测您的应用程序轻松地将其识别。 这种情况下,我相信您能够想出一个有效的替换方法来实现 containsValue() 提供的等效功能。 但如果想不出办法,则一个可行的解决方案是再创建一个 Map,并将第一个 Map 的所有值作为键。 这样,第一个 Map 上的 containsValue() 将成为第二个 Map 上更有效的 containsKey()。

字符串操作

String类对象的常用操作及方法
在Java中,String类包含有50多个方法来实现字符串的各种操作,以下介绍一些我们需要经常使用的方法.
(1)字符串的连接
public String concat(String str)
该方法的参数为一个String类对象,作用是将参数中的字符串str连接到原来字符串的后面.
(2)求字符串的长度
public int length()
返回字串的长度,这里的长度指的是字符串中Unicode字符的数目.
(3)求字符串中某一位置的字符
public char charAt(int index)
该方法在一个特定的位置索引一个字符串,以得到字符串中指定位置的字符.值得注意的是,在字符串中第一个字符的索引是0,第二个字符的索引是1,依次类推,最后一个字符的索引是length()-1.
(4)字符串的比较
比较字符串可以利用String类提供的下列方法:
1)public int compareTo(String anotherString)
该方法比较两个字符串,和Character类提供的compareTo方法相似,Character类提供的compareTo方法比较的是两个字符类数据,而这里比较的是字符串数据.
其比较过程实际上是两个字符串中相同位置上的字符按Unicode中排列顺序逐个比较的结果.如果在整个比较过程中,没有发现任何不同的地方,则表明两个字符串是完全相等的,compareTo方法返回0;如果在比较过程中,发现了不同的地方,则比较过程会停下来,这时一定是两个字符串在某个位置上不相同,如果当前字符串在这个位置上的字符大于参数中的这个位置上的字符,compareTo方法返回一个大于0的整数,否则返回一个小于0的整数.
2)public boolean equals(Object anObject)
该方法比较两个字符串,和Character类提供的equals方法相似,因为它们都是重载Object类的方法.该方法比较当前字符串和参数字符串,在两个字符串相等的时候返回true,否则返回false.
3)public boolean equalsIgnoreCase(String anotherString)
该方法和equals方法相似,不同的地方在于,equalsIgnoreCase方法将忽略字母大小写的区别.
(5)从字符串中提取子串
利用String类提供的substring方法可以从一个大的字符串中提取一个子串,该方法有两种常用的形式:
1)public String substring(int beginIndex)
该方法从beginIndex位置起,从当前字符串中取出剩余的字符作为一个新的字符串返回.
2)public String substring(int beginIndex, int endIndex)
该方法从当前字符串中取出一个子串,该子串从beginIndex位置起至endIndex-1为结束.子串返的长度为endIndex-beginIndex.
(6)判断字符串的前缀和后缀
判断字符串的前缀是否为指定的字符串利用String类提供的下列方法:
1)public boolean startsWith(String prefix)
该方法用于判断当前字符串的前缀是否和参数中指定的字符串prefix一致,如果是,返回true,否则返回false.
2)public boolean startsWith(String prefix, int toffset)
该方法用于判断当前字符串从toffset位置开始的子串的前缀是否和参数中指定的字符串prefix一致,如果是,返回true,否则返回false.
判断字符串的后缀是否为指定的字符串利用String类提供的方法:
public boolean endsWith(String suffix)
该方法用于判断当前字符串的后缀是否和参数中指定的字符串suffix一致,如果是,返回true,否则返回false.
(7)字符串中单个字符的查找
字符串中单个字符的查找可以利用String类提供的下列方法:
1)public int indexOf(int ch)
该方法用于查找当前字符串中某一个特定字符ch出现的位置.该方法从头向后查找,如果在字符串中找到字符ch,则返回字符ch在字符串中第一次出现的位置;如果在整个字符串中没有找到字符ch,则返回-1.
2)public int indexOf(int ch, int fromIndex)
该方法和第一种方法类似,不同的地方在于,该方法从fromIndex位置向后查找,返回的仍然是字符ch在字符串第一次出现的位置.
3)public int lastIndexOf(int ch)
该方法和第一种方法类似,不同的地方在于,该方法从字符串的末尾位置向前查找,返回的仍然是字符ch在字符串第一次出现的位置.
4)public int lastIndexOf(int ch, int fromIndex)
该方法和第二种方法类似,不同的地方在于,该方法从fromIndex位置向前查找,返回的仍然是字符ch在字符串第一次出现的位置.
(8)字符串中子串的查找
字符串中子串的查找与字符串中单个字符的查找十分相似,可以利用String类提供的下列方法:
1)public int indexOf(String str)
2)public int indexOf(String str, int fromIndex)
3)public int lastIndexOf(String str)
4)public int lastIndexOf(String str, int fromIndex)
(9)字符串中字符大小写的转换
字符串中字符大小写的转换,可以利用String类提供的下列方法:
1)public String toLowerCase()
该方法将字符串中所有字符转换成小写,并返回转换后的新串.
2)public String toUpperCase()
该方法将字符串中所有字符转换成大写,并返回转换后的新串.
(10)字符串中多余空格的去除
public String trim()
该方法只是去掉开头和结尾的空格,并返回得到的新字符串.值得注意的是,在原来字符串中间的空格并不去掉.
(11)字符串中字符的替换
1)public String replace(char oldChar,char newChar)
该方法用字符newChar替换当前字符串中所有的字符oldChar,并返回一个新的字符串.
2)public String replaceFirst(String regex, String replacement)
该方法用字符串replacement的内容替换当前字符串中遇到的第一个和字符串regex相一致的子串,并将产生的新字符串返回.
3)public String replaceAll(String regex, String replacement)
该方法用字符串replacement的内容替换当前字符串中遇到的所有和字符串regex相一致的子串,并将产生的新字符串返回.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 基础核心总结》 Java 概述 什么是 Java2 Java 的特点Java 开发环境 JDK JRE Java 开发环境配置 Java 基本语法 数据类型基础语法运算符 Java 执行控制流程条件语句 if 条件语句 if...else 条件语句if...else if 多分支语句switch 多分支语句 循环语句 while 循环语句do...while 循环for 循环语句 跳转语句 break 语句 continue 语句面向对象 类也是-种对象对象的创建 属性和方法 构造方法 方法重载 方法的重写 初始化 类的初始化 成员初始化 构造器初始化初始化顺序 数组初始化 对象的销毁 对象作用域 this 和 super 访问控制权限继承 多态组合代理 向上转型static final 接口和抽象类接口 抽象类异常 认 识 Exception 什么是 Throwable 常见的 Exception 与 Exception 有关的 Java 关键字 throws 和 throw try 、finally 、catch 什么是 Error 内部类 创建内部类集合 Iterable 接口顶层接口 ArrayList Vector LinkedList 类Stack HashSet TreeSet LinkedHashSet 类 PriorityQueue HashMap TreeMap 类 LinkedHashMap 类 Hashtable 类IdentityHashMap 类WeakHashMap 类 Collections 类集合实现类特征图 泛形 泛型的使用 用泛型表示类 用泛型表示接口泛型方法 泛型通配符 反射 Class 类Field 类Method 类ClassLoader 类 枚举 枚举特性 枚举和普通类-样枚举神秘之处 枚举类 I/O File 类 基础 IO 类和相关方法InputStream OutputStream Reader 类Writer 类 InputStream 及其子类 OutputStream 及其子类Reader 及其子类Writer 及其子类 注解 关于 null 的几种处理方式大小写敏感 null 是任何引用类型的初始值 null 只是-种特殊的值使用 Null-Safe 方法null 判断 关于思维导图 Java.IO Java.lang Java.math Java.net Java 基础核心总结 V2.0 IO 传统的 BIO BIO NIO 和 AIO 的区别什么是流 流的分类 节点流和处理流 Java IO 的核心类 File Java IO 流对象 字节流对象InputStream OutputStream 字符流对象Reader Writer 字节流与字符流的转换新潮的 NIO 缓冲区(Buffer)通道(Channel) 示例:文件拷贝案例 BIO 和 NIO 拷贝文件的区别操作系统的零拷贝 选择器(Selectors) 选择键(SelectionKey) 示例:简易的客户端服务器通信 集合 集合框架总览 -、Iterator Iterable ListIterator 二、Map 和 Collection 接口Map 集合体系详解 HashMap LinkedHashMap TreeMap WeakHashMap Hashtable Collection 集合体系详解 Set 接口 AbstractSet 抽象类SortedSet 接口HashSet LinkedHashSet TreeSet List 接口 AbstractList 和 AbstractSequentialList Vector Stack ArrayList LinkedList Queue接口Deque 接口 AbstractQueue 抽象类LinkedList ArrayDeque PriorityQueue 反射的思想及作用 反射的基本使用 获取类的 Class 对象构造类的实例化对象获取-个类的所有信息 获取类的变量(Field) 获取类的方法(Method) 获取类的构造器(Constructor) 获取注解 通过反射调用方法反射的应用场景 Spring 的 IOC 容器反射 + 抽象工厂模式 JDBC 加载数据库驱动类反射的优势及缺陷 增加程序的灵活性破坏类的封装性 性能损耗 代理模式 静态代理与动态代理常见的动态代理实现JDK Proxy CGLIB JDK Proxy 和 CGLIB 的对比动态代理的实际应用 Spring AOP 变量 变量汇总实例变量 实例变量的特点全局变量 静态变量 静态变量的特点类变量 局部变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值