Scala入门

package main.scala

object HelloWorld {
  def main(args: Array[String]) {
        println("Hello World")
    /*
    * 1 变量与常量
    * */
    val str : String = "hello World!"
    val str1 = "hello"

    val a1 = 1 + 1
    val a2 = 1. + (1)

    //不带参数的方法 ()可以省略
    val str2 = 1.toString()
    val str3 = 2.toString
    val str4 = 3 toString

    /*
    * apple:每个scala类中都会有apply方法 不同的类这个方法作用不同
    * String:apply(取出字符串中的某个字符)
    * */
    val str5 = "hello"(0)
    val str6 = "hello".apply(0)
    print(str6 + "|" + str5)

    //Array.apply 创建数组对象
    //array2 可以调用一些方法
    val array = (1,2,3)
    val array2 = Array.apply(1,2,3)
    print(array + "|" + array2)

    //BigInt.apply创建一个大整数
    val bigInt = 1203823121
    val bigInt1 = BigInt.apply(1214123123)
    println(bigInt + "|" + bigInt1)


    //函数 相当于java中的静态方法
    import scala.math._
    val m1 = min(1,3)

    //scala中的方法,通过对象 调用
    val dou1 = 1.toDouble
    val dou2 = dou1 * 2

    /*
    * scala中的控制语句
    * 判断
    * java中的判断 分为 if else | switch case
    * scala中判断 有: if else
    * */
    val x = 1
    val i1 =if(x > 0) x else 0
    //  相当于java中的  ?:

    //假如scala中有多行代码 并且要在一行中写 yong;进行分割
    if(x > 0) {print(x); x + 1}
    if(x > 0){
      print(x)
      x + 1
    }

    //循环
    // <- :循环符号
    //while
    //do while
    //for
    /*
    * java:
    * for(int i = 1 ; i <= 5 ; i ++)
    * */
    for(i <- 1 to 5){
      println(i + " ")
    }
    //to包含最后一位
    //until不包含最后一位
    for(i <- 1 until 5){
      println(i + " ")
    }
    
      for(i <- 0 until "hello".length) {
      print("hello"(i) + "  ")
    }

    val str8 = "hello world"
    println("========================")
    for(i <- 0 until str8.length){
      print(i + " ")
      print(str8(i))
    }

    /*
    * scala中没有break和continue语句
    * 可以使用判断
    *
    * 嵌套函数 :return
    * 使用return返回函数 会导致可读性下降
    * 不推荐
    *
    * Breakable
    * 内部采用捕捉异常的方式退出,执行一次Break 程序就要抛出一次异常
    * 不推荐
    * */

    import scala.util.control.Breaks


    println()
    println("***************")
    for(i <- 1 to 3; j <- 1 to 3 ){
      print((1 * 10) + j + " ")
    }


    /*
    * yeild:关键字 是指 在循环的
    * */
    // 多定义for循环 相当于java中的循环嵌套
    for(i <- 1 to 3; j <- 1 to 3 ) {
      print((i * 10 + j) + " ")
    }
    /*
      for(int i = 1 ; i <= 3 ; i ++) {
        for(int j = 1 ; j <= 3; j ++) {

        }
      }
     */
    println
    for(i <- 1 to 3; j <- 1 to 3 if i != j) {
      print((i * 10 + j) + " ")
    }

    println
    // HIeflmlmop
    // vector : String 类型 for 最终的返回值是与外层循环的取值范围有关系
    // yield 关键字 是指 在循环操作时,对循环变量添加计算表达式.
    val vector = for(c <- "Hello";i <- 0 to 1) yield (c + i).toChar;
    println(vector)
    // 也可以直接取数组元素
	//    for(f <- (1,2,3)) {
    //      println(f)
    //    }
    val vector1 = for(i <- 0 to 1;c <- "Hello") yield (c + i).toChar;
    println(vector1);
    println()
    //val mm = 3
    val vector = for(i <- 1 to 10) yield i*2
    print(vector)
    val t = Array("spark", "python", "java")
    val s = Set("spark", "scala", "java", "hadoop")
    val result = for {
      i <- s
      if t.contains(i)
    } yield {
      i.map(c => (c+1).toChar)
    }

    println(
      """
        |yield的用法总结
        |针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
        |当循环结束后, 会返回所有 yield 的值组成的集合.
        |返回集合的类型与被遍历的集合类型是一致的.
      """.stripMargin)
    println(result)
    println("遍历结果")
    result.foreach(println(_))
  }

}

数组

package com.sk.scala.Arrays

object TestArrays {
  def main(args: Array[String]) {
    // 定长数组
    val nums = Array[Int](10)
    val a = new Array[String](10)
    val s = Array("hello",1)
    // 数组取值
    s(0) = "xxx"

    // 变长数组(缓冲区)
    // 需要导入包scala.collection.mutable.ArrayBuffer
    import scala.collection.mutable.ArrayBuffer

    val b = ArrayBuffer[Int]() // 或 ArrayBuffer
    b += 1  // 使用+= 在数组尾端添加元素
    b += (2,3,5) // 尾端添加多个元素
    b ++= List(11,12,13) // 使用++= 在尾端添加任意集合
    
    // b (1,2,3,5,11,12,13)

    b.trimEnd(5) //移除最后5个元素
    // b(1,2)

    b.insert(2,6) //在下标2之前插入元素6
    // b(1,2,6)
    b.insert(2,7,8,9) //在下标2之前插入多个元素
    // b(1,2,7,8,9,6)

    b.remove(2) //移除下标2的元素, 同时缓冲区的长度也会发生变化.在循环操作时慎用
    // b(1,2,8,9,6)
    b.remove(2,3) // 下标2开始,删除3个元素
    // b(1,2)
    val arr_b = b.toArray //将缓冲区转换成数组

    println(b)

    // 遍历数组
    // until 是 RichInt的方法, 返回所有小于但不包括上限的数组
    // 0 until b.length   ====  0.until(b.length)
    println("------------遍历数组所有元素-------------")
    for(i <- 0 until b.length) {
      println(i + ":" + b(i))
    }
    println("------------每两个元素一跳-------------")
    for(i <- 0 until (b.length,2)) {
      println(i + ":" + b(i))
    }
    println("------------数组反向遍历-------------")
    for(i <- (0 until b.length).reverse) {
      println(i + ":" + b(i))
    }
    println("------------数组元素迭代-------------")
    for(elem <- b) {
      println(elem)
    }

    // 数组转换 指的是数组的计算
    val c = Array[Int](1,2,3,4,5,7,9)
    val result = for(elem <- c) yield 2*elem
    print("数组迭代计算(转换) :")
    for(elem <- result) print(elem + " ")
    println

    // 在执行数组转换操作时, 不会影响原数组,生成新的数组.

    val result2 = for(elem <- c if elem % 2 == 0) yield 2*elem
    print("只计算偶数元素 :")
    for(elem <- result2) print(elem + " ")
    println

    // _ 通配所有数组元素
    // filter 过滤元素
    // filter(_%2==0) 取出数组中的偶数,并存放在新的数组中
    // map将新数组中的所有元素进行相应处理
    val result3 = c.filter(_ % 2 == 0).map(2 * _) // val result4 = c filter(_ % 2 == 0) map(2 * _)
    print("只计算偶数元素(方法2): ")
    for(elem <- result3) print(elem + " ")
    println

    val r4 = c filter(_%2==0) map(2*_)

    /*
      给定一个整数的数组缓冲,移除除第一个负数之外的所有负数.
     */
    // 传统做法  -- 数组缓冲区
    val d = ArrayBuffer(1,2,-1,-2,1,-2) // (1,2-1,1)
    var first = true
    var n = d.length // 6
    var i = 0  //下标
    while(i < n) {
      if(d(i) >= 0) {
        i += 1
      } else {
        if(first) {
          first = false
          i += 1
        } else {
          d.remove(i)
          n -= 1
        }
      }
    }
    println("--------------------")
    for(a <- d) println(a)

    // 方法2
    val d2 = ArrayBuffer(1,2,-1,-2,1,-2)
    var f2 = true
    // 收集需要保留的下标
    var indexes = for(i <- 0 until d2.length if first || d2(i) >= 0) yield {
      if(d2(i) < 0) first = false ; i
    }
    // (0,1,2,4)
    // 将元素移动到该去的位置,并截断尾端 (1,2,-1,1,-2,-2)
    for(j <- 0 until indexes.length) d2(j) = d2(indexes(j))
    d2.trimEnd(d2.length - indexes.length)

    // 常用算法
    // 元素求和
    val sm = Array(1,7,2,9).sum
    // 元素最大值\最小值  max\min
    val m = Array(1,7,2,9).max // min
    // 排序 sort
    // 基于sortBy的第二种实现比较优雅,语义比较清晰,第三种灵活性更强,但代码稍加繁琐
    val e = ArrayBuffer(1,7,2,9)
    val asc = e.sorted // 升序
    val desc = e.sorted.reverse //降序

    val asc1 = e.sortBy(e=>e)
    val desc1 = e.sortBy(e=>e).reverse

    val asc2 = e.sortWith(_<_)
    val desc2 = e.sortWith(_>_)
    /*
    sorted:适合单集合的升降序

    sortBy:适合对单个或多个属性的排序,代码量比较少,推荐使用这种

    sortWith:适合定制化场景比较高的排序规则,比较灵活,也能支持单
    个或多个属性的排序,但代码量稍多,内部实际是通过java里面的Comparator接口来完成排序的。
    sortWith : 可以进行对象排序.
     */

    // 对数组进行排序 , 不能对数组缓冲区进行排序
    val arr = Array(1,7,2,4)
    scala.util.Sorting.quickSort(arr);


    //--------------- 以上数组元素类型必须支持比较操作
    // mkString 指定分割符 Array
    arr.mkString("and")  //(1,2,3)  ==> 1 and 2 and 3
    arr.mkString("<",",",">") // (1,2,3) ==> <1,2,3> :String


    // 多维数组 调用ofDim 方法生成多维数组
    val matrix = Array.ofDim[Double](3,4)  //3行4列
    matrix(1)(2) = 3.2

    // 不规则多维数组
    val triangle = new Array[Array[Int]](10)
    for(i <- 0 until triangle.length)
      triangle(i) = new Array[Int] (i + 1)
    /*
      (v)
      (v,v)
      (v,v,v)
      (v,v,v,v)
      .........
     */

  }
}

============================
TestMap.scala

     package com.sk.scala.map

import scala.collection.mutable
object TestMap {
  def main(args: Array[String]) {
    /********* 映射定义 *********/

    // 定长映射
    val m1 = Map("k1" -> 1, "k2" -> 2, "k3" -> "3")
    val m1_ = Map(("k1",1),("k2",2),("k3","3"))
    // 可变映射1. 带初始值
    var m2 = mutable.Map("k1" -> 1, "k2" -> 2, "k3" -> "3")
    // 可变映射2.
    val m3 = new mutable.HashMap[String,Int]

    /********* 映射取值 *********/

    // 映射取值
    val v1 = m1("k1")

    // 如果映射不包含请求中的键,则报异常 , 解决方法
    val v2 = if(m1.contains("k1")) m1("k1") else 0
    // 以上代码等同于
    val v3 = m1.getOrElse("k1",0)

    // get方法返回Option对象  --> 模式匹配
    val option = m1.get("k1")

    /********* 映射更新值 *********/
    // 更新值
    m2("k1") = 15
    // 增加映射
    m2 += ("k4" -> 15,"k5" -> 16)
    m2 += ("k6" -> 15)

    // 移除映射
    m2 = m2 - "k4" // 必须使用变量
    m2 -= "k4"
    
    // 定长映射不可更新,但可用来计算
    val newMap = m1 + ("k4" -> 15,"k5" -> 16)

    // 可使用变量做更新
    var m4 = Map("k1" -> 1, "k2" -> 2, "k3" -> "3")
    m4 += ("k4" -> 4)
    m4 = m4 - "k4"

    /********* 迭代映射 *********/
    // 键值对迭代
    for((k,v) <- m1) {
      println(m1(k))
      println(v)
    }
    // 值迭代
    for(v <- m1)
      println(v)

    // 键迭代
    for(k <- m1){
      //无法通过m1(k) 进行取值
    }

    // 映射反转
    for((k,v) <- m1) yield (v,k)

    // 平衡二叉树映射
    val tree1 = scala.collection.immutable.SortedMap("k1" -> 1, "k2" -> 2, "k3" -> "3")

  }
}

Tuple.scala

package com.sk.scala.map


/**
  * 元组: 不同类型值得聚集
  */
object Tuple {
  def main(args: Array[String]) {
    // 元组定义
    val t1:Tuple3[Int,Double,java.lang.String] = (1,3.14,"f")
    // 简写
    val t2 = (1,3.14,"f")

    // 访问元组数据
    println(t2._2) // 元组的各组元从1开始
    println(t2 _3)

    // 通过模式匹配获取元组的组元
    val (first,second,third) = t2

    println(first)

    // 可以只获取需要的组元,不需要的使用_代替
    val (first1,_,_) = t2

    // 元组用于函数需要返回不止一个值时,
    val t3 = "Hello".partition(_.isUpper) // (H,ello)
    println(t3._2)

    //********* 拉链操作 *********/
    // 使用元组可以把多个值绑定在一起,以便一起处理,可使用zip方法完成
    val s = Array("<","-",">")
    val c = Array(2,10,2)
    val p = s.zip(c)  // Array(("<",2),("-",10),(">",2))

    // 一起处理
    for((s,n) <- p) println(s * n)

    // 可将对偶集合转化为Map
    val m = s.zip(c).toMap

  }
}

练习

0
1.
设置一个映射,其中包含你想要的一些设备,以及他们的价格。然后构建另外一个映射,采用同一个组件,价格上打九折
0
2.
编写一段程序,从文件中读取单词,用一个可变映射来清点每一个单词出现的频率。
读取这些单词的操作可以使用java.util.Scanner
val in = new java.util.Scanner(new java.io.File(“xxx.txt”))
while(in.hasNext()) // 处理in.next
最后 打印出单词和他们出现的次数


var store = mutable.Map("basketball" -> 20, "soccer" -> 25, "pingpang" -> 5)
var store2 = mutable.Map()

for((k,v) <- store) {
	
	name = store1(k)
	v2 = v * 0.9	

	store2 += (name -> v2)
    }

2

import scala.io.Source

object Test {
   def main(args: Array[String]) {
      println("文件内容为:" )

      Source.fromFile("test.txt" ).foreach{ 
         print 
      }
   }
}



import scala.io.Source
object WordCounts {
  /*
  * 从本地读取文件统计个数
  * */
  def main(args: Array[String]): Unit = {
    val  lines=Source.fromFile("./words.txt").getLines().toBuffer
    //val lines=lines.map(_.split(" ")).flatten.map(t=>(t,1)).groupBy(_._1).map(x=>(x._1,x._2.size)).toList.sortBy(_._2).reverse
    val lines1=lines.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map(t=>(t._1,t._2.size)).toList.sortBy(_._2).reverse
    println(lines1)
  }
}

【scala练习】
1. 编写一个函数countdown(n) ,打印从n到0的数字
2. 编写一个函数product(s:String) ,计算字符串中所有字母Unicode码的乘积
3. 编写一个循环,将整数数组中的元素进行顺序排列
4. 编写一段代码,去掉数组中所有的重复项
5. 编写一个函数minmax(values:Array[Int]),返回数组中最小值和最大值的对偶
6. 编写一个函数Iteqgt(values:Array[Int],v:Int),返回数组中小于v、等于v和大于v的数量,要求三个数一起返回
7. 彩票小程序
	① 输入7个 1~35 的数字(用户购买彩票) 
	② 随机生成7个数字,系统自动兑奖并返回中奖结果

==============================
	1
		def countdown(n: Int) = {
  			for(i <- (0 to n).reverse) println(i)
		}

		def countdow(n: Int) : Unit = {
     		if(n <= 0) println(0) else { println(n); countdow(n - 1) }
   		}
		

	2
			def countUnicode(text: String) = {
		    var ans: Long = 1
		    for (s <- text){
		      ans *= s.toLong
		    }
		    ans
		  }

	3 	
		Arrays.sort(arr)

		  

        def sortArr(arr : int [])={
        	for(i <- (0 to n - 1)){
        		for(j <- (0 to n)){
        			if (int[i] > int[j]){
        				int temp = arr[i]
        				arr[i] = arr[j]
        				arr[j] = temp
        			}
        		}
        	}
        }

    4 
    	def func6(arr: Array[Int]) = {
    		arr.toBuffer.distinct.toArray
  		}
  		/*    这个distinct方法返回一个新的集合,重复元素只保留一份。记得使用一个新的变量来指向这个新的集合,无论你使用的是mutable集合还是immutable集合。*/


  	5
  		object HelloScala{

		  def main(args: Array[String]): Unit= {

		    val array=Array(1,2,3,4,5)

		    var tuple:(Int,Int)=minmax(array)

		    println(tuple._1+" "+tuple._2)

		  }

		  def minmax(arr:Array[Int])={

		    (arr.min,arr.max)

		  }

		}


	6
		def iteqgt(values:Array[Int],v:Int)={
		  val buf = values.toBuffer  (
		  	values.count(_ < v),values.count(_ == v),values.count(_ > v)
		  		)
		  	}


	7
		import scala.io._
		object Test {
		   def main(args: Array[int]) {
		      print("请输入您要买的彩票(1~35): " )
		      val line = StdIn.readLine()

		      println("谢谢,购买的彩票是: " + line)
		   }
		   println("彩票中奖号码为:" + index)
		   if(line equals index){
		   	println("恭喜中奖")

		   }
		   else	{"没中奖"}
		}

		def randomNew(n:Int)={
		  var arr= 0 to 35 toArray
		  var outList:List[Int]=Nil
		  var border=arr.length//随机数范围
		  for(i<-0 to 6){//生成n个数
		    val index=(new Random).nextInt(border)
		  }
		  return index
		}



类与对象

1. 简单类
class Counter {
	private var value = 0   // 必须初始化字段
	def increment() {
		value += 1  // 方法默认是共有的
	}
	def current() = { value }
}

2.调用构造方法
	val counter = new Counter // 或 new Counter()
	counter.increment()
	println(counter.current)
	
	调用无参方法时,可以写
	
3.scala中的get/set方法
class Person {
	private var privateAge = 0  //将属性定义为私有并改名
	def age = privateAge // java中的get方法
	def age_$eq(int)   // java中的set方法
}
	- 可以重新定义getter或setter方法
class Person{
	private var privateAge = 0 
	def age = privateAge
	def age_ = (newValue Int){
		if(newValue > privateAge) privateAge = newValue //年龄不能变小
	}
}

	- 使用时仍然可以调用age属性,但是不能变的更小
	val person = new Person
	person .age = 30
	person .age = 21
	println(person.age)  // 打印30
	
	[提示]
		- 如果字段是val,则只有getter方法被生成
		- 如果不需要getter和setter,可将字段声明为private
https://blog.51cto.com/chenshenglong/1421164
4. 辅助构造器
	类似于Java中的带参构造方法
	不同:
		1.辅助构造器的名称为this
		2.每一个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始
class Person {
	private var name = "";
	private var age = 0;
	
	def this(name:String) {
		this() // 调用主构造器
		this.name = name 
	}
	def this(name:String,age:Int){
		this(name)    //调用辅助构造器
		this.age = age
	}
}

	- 调用
		val p1 = new Person
		val p2 = new Person("Fred")
		val p3 = new Person("Fred",42)
5. 主构造器
	1. 主构造器的参数直接放在类名之后
		主构造器的参数被编译成字段,其值被初始化成构造时传入的参数。

	2. 主构造器会执行类定义中的所有语句。
	
	- 在Java中
public class Person {
	private String name;
	private int age ;
	public Person(String name ,int age){
		this.name = name ;
		this.age = age ;
	}
	public String name(){return this.name;}
	public int age(){return this.age;}
	...
}
	-scala
class Person(val name:String,val age:Int) {
	println("Just constructed another person")
	def description = name + " is " + age + " years old "
}
	-> println语句是主构造器的一部分。	每当new时就会调用。

*5. 嵌套类
	在scala中任何语法中都可以嵌套另一语法,可以在函数中定义函数。
import scala.collection.mutable.ArrayBuffer
class Network {
	class Member(val name:String){
		val contarts = new ArrayBuffer(Member)
	}
	
	private val members = new ArrayBuffer[Member]
	
	def join(name:String) = {
		val m = new Member(name)
		members += m
		m
	}
}

以上实例中,假设有两个network
	val chatter = new Network
	val myFace = new Network
	
可以在各自的实例中添加成员,但是不能相互添加成员
	val fred = chatter.join("fred")
	val wilma = chatter.join("wilma")
	fred.contacts += wilma 
	val barney = myFace.join("Barney")
	fred.contacts += barney




对象
---------------
	1. 单例对象
	可实现Java中的静态
object account {
	private var lastNumber = 0
	def newUniqueNumber() = { lastNumber = 1; lastNumber}
}

	与类的区别: 单例对象后无法写参数
	作用:
		- 作为存放工具函数或常量的地方
		- 高效的共享单个不可变实例
		- 需要用单个实例来协调某个服务时(单例模式)
		
	2. 伴生对象
		既有实例方法又有静态方法的类
class Account {
	val id = Account.newUniqueNumber()
	private var balance = 0.0
	def deposit(amount:Double) {balance += amount}
}
objcet Account {
	private var lastNumber = 0 
	private def newUniqueNumber = {lastNumber += 1;lastNumber}
}
	- 类与它的伴生对象可以互相访问私有属性,但是必须在同一源文件中
	
	3. 扩展类或特质的对象
	-- 扩展类 -> Java中接口
abstract class UndoableAction(val description:String) {
	def undo() : Unit
	def redo() : Unit
}
	-- 扩展类的对象
object doNothingAction extends UndoableAction("do nothing") {
	override def undo (){}
	override def redo (){}
}
	-> 实现缺省行为
val actions = Map("open" -> doNothingAction,"save" -> doNothingAction) //打开、保存未实现
	
	4. apply 方法
	定义和使用对象的apply方法来替代构造器(替代new),提高代码的可读性
	Array(100)
		- 调用apply方法生成1个元素为1个100的数组
	new Array(100)
		- 调用this构造器生成1个元素为100个null的数组
	
class Account (val id : Int, initialBalance:Double) {
	private var balance = initialBalance
	...
}
object Account {
	def apply(initialBalance:Double) {
		new Account(newUniqueNumber(),initialBalance)
	}
} 

	5. 应用程序对象
	带有main函数的object ,



	

练习
1.编写一个BankAccount类 , 加入deposit和withdraw方法,和一个只读的balance属性
2.编写一个Time类,加入只读属性bours和minutes,和一个检查某一时刻是否早于另一时刻的
方法before(other:Time):Boolean。Time对象应该以new Time(hrs,min)方式构建。
hrs以0~23之间小时数构建
3.编写一个Person类,其主构造器接受一个字符串,该字符串包含名字、空格和姓。提供只读属
性firstname和lastname

练习
==============
1.编写一个BankAccount类 , 加入deposit和withdraw方法,和一个只读的balance属性

class BankAccount{
	private var privatebalance = 0
	def balance = privatebalance

	def deposit(){}
	def withdraw(){}
}


class BankAccount(val balance:Int = 0){
     //只读
    def deposit(){}
    def withdraw(){}
  }


2.编写一个Time类,加入只读属性bours和minutes,和一个检查某一时刻是否早于另一时刻的
方法before(other:Time):Boolean。Time对象应该以new Time(hrs,min)方式构建。
hrs以0~23之间小时数构建

class Time{
	private var privateboures = 0
	def balance = privatebours

	private var privateboures = 0
	def balance = privatebours

	def before(other:Time):Boolean
	
}

// before(other:Time):Boolean。 Time对象应该以new Times(hrs, min)方式构建,其中hrs小时以
  // 军用时间格式呈现
  class Time(val hours:Int,val minutes:Int ){
    def before(other:Time):Boolean={
      hours < other.hours || (hours == other.hours && minutes < other.minutes )
    }
    override def toString():String = {
      hours + " : " + minutes
    }
  }
3.编写一个Person类,其主构造器接受一个字符串,该字符串包含名字、空格和姓。提供只读属
性firstname和lastname


class Person(val name:String) {
  val firstNmae:String=name.split(" ")(0)
  val lastNmae:String=name.split(" ")(1)
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

oifengo

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值