Scala
函数式编程:感觉spark一般用scala写,甚至spark源码就是用scala实现的,所以就学习一下scala
基础
/** * 基础语法 */object base { def hello1(name:String):String = { s"my name is ${name}" } def hello2(name:String) = s"my name is ${name}" def study_for() = { val li = List(1,2,3,4,5) for( s <- li )println("first_for : "+s) for( s <- li if s > 2 )println("second_for : "+s) println( for( s <- li if s < 3 )yield (s) ) } def study_try() = { try { Integer.parseInt("dog") } catch { case _ => 0 } finally { println("always be printed") } } def study_match(num:Int) = { num match { case 1 => "one" case 2 => "two" case _ => "other" } } def main(args: Array[String]): Unit = {// println(hello1("lilei"))// study_for() println(study_try()) println(study_match(1)) }}
* 函数
/** * 函数 */object functions { //匿名函数 //(参数列表) => {函数体} val sum1 = (a:Int,b:Int) => a + b //函数 def sum2 (a:Int , b:Int) = a+b //高阶函数1 def operate(f:(Int,Int) => Int) = { f(4,4) } //高阶函数2 def greeting1() = (name:String) => {"hello" + " " + name} def greeting2() = (name:String) => s"hello ${name}" def main(args: Array[String]): Unit = { println(sum1(3,4)) println(sum2(3,4)) println(operate(sum1)) println(greeting1()("world")) println(greeting2()("IDEA")) }}
求值策略
两种方式:
- call by value - 对函数实参求值,且仅求值一次
- call by name - 函数实参每次在函数体内被用到才会求值(函数形参以 => 开头)
/** * 求值策略 */object evaluation_strategy { // x: call by value / y: call by name def bar(x:Int, y: =>Int):Int = 1 def loop(): Int = loop def main(args: Array[String]): Unit = { println(bar(1,loop()))// println(bar(loop(),1)) } }
柯里化
/** * 柯里化 */object curried {// def add(x: Int, y: Int) = x + y //非科里化语法// def add(x: Int)(y: Int) = x + y //科里化语法 /** * 柯里化函数:把具有多个参数的函数转换为一条函数链,每个节点上是单一参数 * @ Curried Function */ def curriedAdd(a:Int)(b:Int) = a + b val addOne = curriedAdd(1)_ //相当于从新定义了一个函数 def main(args: Array[String]): Unit = { println(curriedAdd(2)(2)) println(addOne(2)) }}
递归
/** * 递归 recursive */object recursive { /** * 递归函数 */ def factorial1(n:Int): Int = if(n <= 0) 1 else n * factorial1(n - 1) /** * 尾递归函数(Tail Recursive Function) * 所有递归形式的调用出现在函数的末尾 * 当编译器检测到一个函数调用是尾递归,它就覆盖当前的活动记录而不是在栈中去创建一个新的 */ @annotation.tailrec //告诉scala编译器要进行尾递归优化,不写的话不会主动优化 def factorial2(n:Int, m:Int):Int = // m记录每一回合后的阶乘 if (n <= 0) m else factorial2(n-1 , m*n) def main(args: Array[String]): Unit = { println(factorial1(5)) println(factorial2(5,1)) }}
Scala Immutable
list
/** * List[T] */object collections_list { val a = List(1,2,3,4) a.head //首元素 a.tail //尾列表(除了首元素) a.isEmpty //判断是否为空 /** * 遍历 * @param l * @return */ def walkthru(l:List[Int]):String = { if (l.isEmpty) "" else l.head.toString + " " + walkthru(l.tail) } def main(args: Array[String]): Unit = { println(a) val b = 0::a //连接操作符 => 成员 :: List println(b) val c = a:::b println(c) val d =walkthru(a) println(d) val e = a.filter(x => x%2==1 ) println(e) val str = "99 Red Balloons".toList println(str) println(str.filter(x => Character.isDigit(x))) println(str.takeWhile(x => x!='B')) // 返回False的时候takeWhile停止 }}
list-map
object list_map { def main(args: Array[String]): Unit = {// val c = List('x','y','z') val c = "x"::"y"::"z"::Nil// println(c.map(x => x.toUpperCase())) println(c.map(_.toUpperCase())) val a = List(1,2,3,4,5,6) println(a.filter(_ % 2 == 1)) println(a.filter(_ % 2 == 1).map(_ + 10)) val q = List(List(1,2,3),List(4,5,6)) println(q.map(x => x.filter( _%2==0))) println(q.map(_.filter( _%2==0))) //返回值类型跟原来的List一样 println(q.flatMap(_.filter( _%2==0))) //返回值类型是一个List }}
reduceLeft & flodLeft
/** * 函数作为参数,函数参数 => 返回值 */object _Left { def main(args: Array[String]): Unit = {// reduceLeft(op: (T, T) => T) val a = List(1,2,3,4,5) println(a.reduceLeft((x,y) => x + y )) println(a.reduceLeft(_+_))// foldeLeft(z : U)(op: (U, T) => U) println(a.foldLeft(0)(_+_)) }}
Range
/** * 整数序列 */object range { def main(args: Array[String]): Unit = { val a = 1 to 10 println(a) println(a.toList) val b = 1 to 10 by 2 println(b) println(b.toList) val c = 1 until 10 println(c.toList) /* to包含后边界,until不包含 */ }}
Stream
/** * Stream is a lazy List * 惰性求值的列表: * 使用的时候才会处理,避免内存溢出 */object stream { def main(args: Array[String]): Unit = { val a = 1 #:: 2 #:: 3 #:: Stream.empty println(a) val stream = (1 to 1000000).toStream println(stream) println(stream.head) println(stream.tail) }}
Tuple
/** * Tuple 元组 */object tuple { /** * 1:长度 * 2:元素求和 * 3:元素平方和 */// foldeLeft(z : U)(op: (U, T) => U) def sumSq(in: List[Int]):(Int,Int,Int) = in.foldLeft((0,0,0))((t,v) => (t._1 + 1 , t._2 + v , t._3 + v*v)) def main(args: Array[String]): Unit = { val a = (1,2) println(a) val b = 1->2 println(b) val c = (1,"Alice","Math",95.5) println(c) println("1: "+c._1+"\t"+"2: "+c._2+"\t"+"3: "+c._3+"\t\t"+"4: "+c._4) val arr = List(1,2,3,4,5) println(sumSq(arr)) }}
map
/** * Map[K,V] * map的基础操作 */object map { def main(args: Array[String]): Unit = { val m = Map(1->"David",2->"Alice",3->"Elwood") println(m) println(m(1)) /** * value = map(key) */// contains(key) 判断元素在不在map里 println(m.contains(4))// 返回值为Set() => 返回所有的key println(m.keys)// 如上 println(m.values)// 添加元素 val n = m + (8->"Archer") println(n)// 删除元素 val o = m - 1 println(o)// 添加多个元素 val z = m ++ List(6->"test",7->"aaa") println(z)// 删除多个 var x = z -- List(1,6,7) println(x) var y = z ++ List(11->"eleven",12->"twelve") -- List(1,2,3,6,7) println(y) }}
综合案例:
test1:
/** * 函数::综合例子 */object test { def sum( f:Int => Int)(a:Int)(b:Int) :Int = { var num = 0 @annotation.tailrec def loop(n:Int, acc:Int):Int = { if (n > b) {// println(s"n = ${n}\tacc=${acc}") num = acc acc } else {// println(s"n = ${n}\tacc=${acc}") loop(n + 1, acc + f(n)) } } loop(a,0) num } def main(args: Array[String]): Unit = { println(sum(x => x)(1)(5)) println(sum(x => x*x)(1)(5)) println(sum(x => x*x*x)(1)(5)) }}
quick sort:
object quickSort { def qSort(a:List[Int]):List[Int] = if (a.length < 2) a else qSort(a.filter(_ < a.head)) ++ a.filter( _ == a.head) ++ qSort(a.filter( _ > a.head)) def main(args: Array[String]): Unit = { println(qSort(List(9,5,2,4,5,7,1,8,6,4))) }}
第一次接触函数式编程,感觉有些不同点需要消化一下。。。先记录下来。。。