scala基础
For
package com.laoliu.basic import java.io.{File, FileNotFoundException, FileReader, IOException} object For { def main(args: Array[String]): Unit = { val filesHere = (new File(".")).listFiles() // for(file <- filesHere) println(file) // for(i <- 0 to filesHere.length-1) println(filesHere(i)) // for(i <- 1 to 4) println(i) // for (i <- List(1,2,3)) println(i) // for {file <- filesHere // if file.getName.endsWith(".xml") // if file.isFile // } // println(file) // def getFiles:Array[String] = for { // file <- filesHere // if file.getName.endsWith(".xml") // line <- scala.io.Source.fromFile(file).getLines().toList // trimmed = line.trim // if trimmed.matches(".*laoliu.*") // } yield file + ":" + trimmed try { var f = new FileReader("input.txt") } catch { case e @(_:FileNotFoundException | _:IOException) => { println("All exception = " + e.getMessage) } case ex:Exception => { println("ex") } } } }
If While
package com.laoliu.basic object IfAndWhile { def main(args: Array[String]): Unit = { // val filename = if(args.isEmpty) "default.txt" else args(0) // println(filename) // var line = "" //// do { //// line = scala.io.StdIn.readLine() //// println("Read: " + line) //// } while (line != "") // def greet() = {println("hi")} // println(()== greet()) // def func = 789 // // var haha = 123 // haha = func // print(haha) var tempLine = "" while ((tempLine = scala.io.StdIn.readLine()) != "") println("Read: " + tempLine) } }
other
package com.laoliu.basic object Test { def main(args: Array[String]): Unit = { def makeRowSeq(row: Int) = for(col <- 1 to 10) yield { val prod = (row * col).toString val padding = " " * (4 - prod.length) padding + prod } def makeRow(row: Int) = makeRowSeq(row).mkString def multTable() = { var tableSeq = for(row <- 1 to 10) yield makeRow(row) tableSeq.mkString("\n") } println(multTable()) } }
面向对象
package com.laoliu abstract class Element { def contents:Array[String] def height: Int = contents.length def width: Int = if(height == 0) 0 else contents(0).length } class ArrayElement( val contents:Array[String] ) extends Element { final def testFinal = println("test final") } class LineElement(s:String) extends ArrayElement(Array(s)) { override def width: Int = s.length override def height = 1 } object Element { private class LineElement(s: String) extends Element { val contents = Array(s) override def height: Int = 1 override def width: Int = s.length } private class UniformElement( ch:Char, override val width: Int, override val height: Int ) extends Element { private val line = ch.toString * width override def contents: Array[String] = Array.fill(height)(line) } } object Main { def main(args: Array[String]): Unit = { val ele = new LineElement("sss") println(ele.height) println(ele.width) ele.testFinal } }
apply
package com.laoliu import scala.annotation.tailrec class Point(var name:String) {} object Point { def apply(name: String): Point = new Point(name) } object TestApply { def main(args: Array[String]): Unit = { // val p = Point("haha") // println(p.name) // for(i <- 0 to 9)println(i) // for(i <- 0 until 10)println(i) // val arr = Array("apple", "orange", "pear") // for(s <- arr) println(s) // arr.foreach(println) // val tuple = (2, "str", "apple") // println(tuple._3) // val (age, firstName, lastName) = tuple // println(firstName) var args = Array("123", "456", "789") // var i = 0 // while (i < args.length) { // println(args(i)) // i += 1 // } @tailrec def digui(start: Int):Unit = if(start < args.length) { println(args(start)) digui(start + 1) } digui(0) } }
minin
package com.laoliu object TestMinin { } class Point(val x: Int, val y:Int) class Rectangle(val topLeft:Point, val bottomRight:Point) { def left=topLeft.x def right=bottomRight.x def width = right-left } abstract class Component { def topLeft:Point def bottomRight: Point def left = topLeft.x def right = bottomRight.x def width = right - left } trait Rectangular { def topLeft: Point def bottomRight: Point def left = topLeft.x def right = bottomRight.x def width = right - left } class RectangleNew(val topLeft: Point, val bottomRight: Point) extends Rectangular abstract class ComponentNew extends Rectangular abstract class Abc
mins
package com.laoliu object Testmins { def main(args: Array[String]): Unit = { val qu = new BasicIntQueue with Filtering with Incrementing qu.put(-1) qu.put(0) qu.put(1) println(qu.get()) println(qu.get()) println(qu.get()) println(qu.get()) } } abstract class IntQueue { def get(): Int def put(x: Int) } import scala.collection.mutable.ArrayBuffer class BasicIntQueue extends IntQueue { private val buf = new ArrayBuffer[Int] override def get(): Int = buf.remove(0) override def put(x: Int) = { buf += x } } trait Doubling extends IntQueue { abstract override def put(x: Int): Unit = { super.put(2 * x) } } trait Incrementing extends IntQueue { abstract override def put(x: Int): Unit = { super.put(x + 1) } } trait Filtering extends IntQueue { abstract override def put(x: Int): Unit = { if(x>=0) super.put(x) } } class MyQueue extends BasicIntQueue with Doubling package bo { class Ship }
traits
package com.laoliu object TestTraits { def main(args: Array[String]): Unit = { val frog = new Frog frog.philosophize() val phil: Philospphical = frog phil.philosophize() } } trait Philospphical { def method1(): Int def philosophize() = { println("I consume memory, therefore I am!") } } class Animal trait HasLegs class Frog extends Animal with Philospphical with HasLegs { override def method1(): Int = 2 override def toString: String = "green" override def philosophize(): Unit = { println("It ain't easy being " + toString + "!!") } } //trait NoPoint(x:Int, y:Int) //class Point(x:Int)
函数
闭包
package com.laoliu.jinjie /* 闭包:函数会去捕获一个自由变量,如果自由变量more发生改变,则闭包里也会捕获这个改变 var more = 1 val addMore = (x: Int) => x + more 闭项: 函数不需要捕获自由变量 val add = (x: Int) => x + 1 */ object Closures { def main(args: Array[String]): Unit = { var more = 1 val addMore = (x: Int) => x + more println(addMore(10)) val add = (x: Int) => x + 1 more = 999 println(addMore(100)) def makeIncr(more: Int) = (x: Int) => x + more val inc1 = makeIncr(1) val inc999 = makeIncr(999) println(inc1(1)) println(inc999(1)) } }
package com.laoliu.jinjie /* 总结: 1.函数做为一个对象,可以赋值给变量 var increase = (x: Int) => x + 1 2.函数可以作为参数传递 val func = (x: Int) => x > 0 val vals = someNumbers.filter(func) */ object FirstClassFunction { def main(args: Array[String]): Unit = { val someNumbers = List(-11, -10, -5, 0, 5, 10) // someNumbers.foreach(println) val func = (x: Int) => x > 0 val vals = someNumbers.filter(func) // println(vals) def sum(a: Int, b: Int, c:Int) = a + b + c // println(sum(1,2,3)) val aSum = sum _ // print(aSum.apply(1,2,33)) val bSum = sum(1, _:Int, 3) println(bSum(5)) println(bSum(6)) } }
package com.laoliu.jinjie /* 如果是辅助函数,只是在当前功能下使用,在class或object尽量使用private来修饰,这样的函数也称为方法 当然scala也提供本地函数这么一个概念,就是函数里定义函数,本地函数只能在当前函数下调用 */ object LocalFunction { def main(args: Array[String]): Unit = { LongLines.processFile("xxx.txt", 14) } } import scala.io.Source object LongLines { def processFile(filename:String, width: Int) = { def proecssLine(line: String) = { if(line.length > width) println(filename + ":" + line.trim) } val source = Source.fromFile(filename) for(line <- source.getLines()) proecssLine(line) } }
动态传参
package com.laoliu.jinjie /* 1.scala动态传参: 定义时: 参数类型*, 在函数体获取到是一个参数数组 如果把一个array对象传入函数中,调用时需要这么写: arr_var_name: _* val arr = Array("what", "up", "haha") echo(arr: _*) echo() echo("123", "456") def echo(args: String*): Unit = { for(s <- args) println(s) } 2.scala默认支持按照你在定义函数时,给的参数名来传参 当然在定义函数的时候,可以给参数 直接 = 赋个默认值 */ object Parameters { def main(args: Array[String]): Unit = { println(speed(distance = 12, time = 12)) println(speed(time = 12, distance = 24)) def speed(distance: Float, time: Float) = distance / time // val arr = Array("what", "up", "haha") // echo(arr: _*) // echo() // echo("123", "456") // def echo(args: String*): Unit = { // for(s <- args) println(s) // } } }
尾递归
package com.laoliu.jinjie import scala.annotation.tailrec /* 递归和while循环可以相互转化,其中 递归:更函数式、简洁、没有var,但是函数调用会消耗时间 while:运行效率会更高效,不涉及方法调用 尾递归:如果调用自身方法的动作是函数体的最后一个动作的话,那么这个递归就是尾递归 如果是尾递归,编译器会优化,效率和while循环一样 检测是否为尾递归,可以用@tailrec注解 */ object TailRecursion { def main(args: Array[String]): Unit = { @tailrec def boom(x: Int): Int = if(x == 0) throw new Exception("boom") else boom(x - 1) } }
传参
package com.laoliu.ctrldef /* byname 和 byvalue 传参: 主要是在函数定义时 传参的区别,byname传入的是函数, byvalue传入的是值 并在byvalue在传入时,就会运行好,把运行结果传下去 而byname 则是在调用函数执行 */ object ByNameParam { def main(args: Array[String]): Unit = { var flag = false def my(pre: () => Boolean) = { if(flag && !pre()) throw new AssertionError } // 上面支持 这么调用,但是不满足简洁阅读习惯 my(() => 5 > 3) // 我们希望看到这样调用,但是这个会编译报错 // my(5 > 3) //如果想实现上面效果,可以在定义去掉参数的那空括号就可以,如下代码: def b1(pre: => Boolean) = { if(flag && !pre) throw new AssertionError } b1(5>3) def b2(pre: Boolean) = { if(flag && !pre) throw new AssertionError } val x = 5 b1(x / 0 == 0) // b2(x / 0 == 0) } }
柯里化
package com.laoliu.ctrldef import java.io.{File, PrintWriter} /* 控制结构的实现: 利用函数可以作为参数进行传递,其中代码结构相同里面的差异代码 就是封装在这个传递函数中 多个参与 采用柯里化的方式 f(var1)(var2),其中var2的括号可以变成{} */ object ControlStructureDef { def main(args: Array[String]): Unit = { def twice(op: Double => Double, x: Double) = op(op(x)) println(twice(_ + 1, 5)) def withPrintWriter(file: File, op: PrintWriter => Unit): Unit = { val writer = new PrintWriter(file) try { op(writer) } finally { writer.close() } } withPrintWriter( new File("date.txt"), writer => writer.println(new java.util.Date) ) def until(condition: => Boolean) (block: => Unit): Unit = { if(!condition) { block until(condition)(block) } } var i = 10 until(i == 0){ println(i) i-=1 } } }
package com.laoliu.ctrldef /* 柯里化的本质就是 函数可以作为另外一个函数的返回值 其中还用到了闭包 //柯里化函数 def curriedSum(x: Int)(y:Int) = x + y println(curriedSum(1)(2)) //柯里化过程 def first(x: Int) = (y: Int) => x + y val second = first(1) println(second(2)) */ object Currying { def main(args: Array[String]): Unit = { def addFunc(): Int => Int = { (x: Int) => x + 1 } println(addFunc()(1)) //柯里化函数 def curriedSum(x: Int)(y:Int) = x + y println(curriedSum(1)(2)) //柯里化过程 def first(x: Int) = (y: Int) => x + y val second = first(1) println(second(2)) val one = curriedSum(1)_ println(one(5)) } }
高阶函数
package com.laoliu.ctrldef /* 高阶函数 就是用函数作为参数的函数 使用高阶函数有这么两个特点: 减少冗余代码 客户端代码更简洁 高阶函数定义精髓: 一系列的操作,具有相同代码的结构,定义函数定义好这个代码结构 抽离不同的部分,通过函数传递过来 注意:其中的闭包传递 */ object HighOrderFunctions { def main(args: Array[String]): Unit = { println(List(1,2,3,4).exists(_ < 0)) } } object FileMatcherNew { private def filesHere = (new java.io.File(".")).listFiles //利用高阶函数减少冗余代码,如过是java的话,就需要新建一个接口,然后是一大堆的匿名内部类 private def filesMatching(matcher: String => Boolean) = for (file <- filesHere; if matcher(file.getName)) yield file def filesEnding(query: String) = filesMatching(_.endsWith(query)) def filesContaining(query: String) = filesMatching(_.contains(query)) def filesRegex(query: String) = filesMatching(_.matches(query)) }