scala和java都是在jvm之上的语言,相对来讲,scala热度比较低,其实并不是一个特别好的语言选择。
原因倒不是因为scala本身的缺点,而是使用人群不够多,论坛和社区不够活跃。这就跟社交软件一样,大家都用微信,短信就没人用了。
但是scala是写分布式程序的一门非常方便的语言,因为scala几乎每个对象都有map,reduce,filter等方法,这跟spark的用法简直如出一辙。
多范式
scala是一种多范式的语言,这也没啥特别的,就是既能面向过程又能面向对象,比如C++就是多范式。
安装
装scala要先装java,再装scala。
交互式编程
scala支持像javascript那种交互式编程,在命令行输入scala,进入交互式编程控制台。
编译
scalac 约等于 javac
打包和引包
打包有两种,第一种和java一样,在首行用package关键字。先掌握这种就行了。
引包也是用import但功能比java要强大,可以在代码任意位置引。
import java.awt.{Color, Font} // 重命名成员 import java.util.{HashMap => JavaHashMap} // 隐藏成员 import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了
默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,这里也能解释,为什么以scala开头的包,在使用时都是省去scala.的。
数据类型
scala多了几种比较傻又还是有点用的数据类型:
Unit 类似于void
Null 等于null
Nothing 是所有类的子类
Any 约等于 Object
常量和变量声明
常量: val x:String ="a";
变量 var x:String ="a";
访问修饰符
private ,protect,public default是public。有一些些区别,比如可灵活指定范围 private[ClassA]表示ClassA能访问。
运算符
基本运算符完全一致,不用特地去看。
针对集合或者是特殊对象有一些运算符,如List中(::,:::),Set中(&,++)等,运算符也可以作为方法使用。
if...else
完全一致,不用特地去看。
循环
终止循环。scala不支持break和continue关键字,scala2.8之后加入了 Breaks类,使用如下写法:
// 导入以下包 import scala.util.control._ // 创建 Breaks 对象 val loop = new Breaks; // 在 breakable 中循环 loop.breakable{ // 循环 for(...){ .... // 循环中断 loop.break; } }
for循环比较好用,java感觉也是借鉴了该思想:
//1到10 for( var x <- 1 to 10 ){ statement(s); } //1到9 for( var x <- 1 until 10 ){ statement(s); } //双循环,java里面需要两个for for( a <- 1 to 3; b <- 1 to 3){ println( "Value of a: " + a ); println( "Value of b: " + b ); } //集合 for(x<- List) { } //循环过滤 感觉不需要掌握,放在循环体内也可以。 for( a <- numList if a != 3; if a < 8 ){ println( "Value of a: " + a ); } //yield 注意for后面是大括号 用于返回满足条件的所有a集合里面的值,生成新集合 var retVal = for{ a <- numList if a != 3; if a < 8 }yield a
方法声明
在java中是先声明出参再声明入参,scala正好相反。只是思维方式不一样。
object add{
def addInt( a:Int, b:Int ) : Int = { var sum:Int = 0 sum = a + b return sum } }
函数声明
函数是scala函数式编程的重点,会在下一篇文章中重点介绍。
字符串
scala字符串是不能更新的所以对字符串变量的修改会在内存区域创建一个新的字符串对象,如果需要更新,可以用StringBuilder这个对象。
集合:
scala集合包括java中常见的那些集合(List,Set,Map),以及元组,与java不同的是,scala中的集合一般是不可变集合,修改集合的实现是创建一个新的集合。
链表(List)
列表的元素类型 T 可以写成 List[T]。
构造列表的两个基本单位是 Nil 和 :: 。 Nil 也可以表示为一个空列表。
scala的类java构造数组办法。
// 字符串列表 val site: List[String] = List("Runoob", "Google", "Baidu") // 整型列表 val nums: List[Int] = List(1, 2, 3, 4) // 空列表 val empty: List[Nothing] = List() // 二维列表 val dim: List[List[Int]] = List( List(1, 0, 0), List(0, 1, 0), List(0, 0, 1) )
scala特有的构造办法如下:
// 字符串列表 val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil)) // 整型列表 val nums = 1 :: (2 :: (3 :: (4 :: Nil))) // 空列表 val empty = Nil // 二维列表 val dim = (1 :: (0 :: (0 :: Nil))) :: (0 :: (1 :: (0 :: Nil))) :: (0 :: (0 :: (1 :: Nil))) :: Nil
连接列表的操作
你可以使用 ::: 运算符或 List.:::() 方法或 List.concat() 方法来连接两个或多个列表。实例如下:
object Test { def main(args: Array[String]) { val site1 = "Runoob" :: ("Google" :: ("Baidu" :: Nil)) val site2 = "Facebook" :: ("Taobao" :: Nil) // 使用 ::: 运算符 var fruit = site1 ::: site2 println( "site1 ::: site2 : " + fruit ) // 使用 List.:::() 方法 fruit = site1.:::(site2) println( "site1.:::(site2) : " + fruit ) // 使用 concat 方法 fruit = List.concat(site1, site2) println( "List.concat(site1, site2) : " + fruit ) } }
集合(Set)
可变集合和不可变集合。 虽然可变Set和不可变Set都有添加或删除元素的操作,但是有一个非常大的差别。对不可变Set进行操作,会产生一个新的set,原来的set并没有改变,这与List一样。 而对可变Set进行操作,改变的是该Set本身,与ListBuffer类似。
import scala.collection.mutable.Set // 可以在任何地方引入 可变集合 val mutableSet = Set(1,2,3) println(mutableSet.getClass.getName) // scala.collection.mutable.HashSet mutableSet.add(4) mutableSet.remove(1) mutableSet += 5 mutableSet -= 2 println(mutableSet) // Set(5, 3, 4) val another = mutableSet.toSet println(another.getClass.getName) // scala.collection.immutable.Set
你可以使用 ++ 运算符或 Set.++() 方法来连接两个集合。如果元素有重复的就会移除重复的元素。实例如下:
object Test { def main(args: Array[String]) { val site1 = Set("Runoob", "Google", "Baidu") val site2 = Set("Faceboook", "Taobao") // ++ 作为运算符使用 var site = site1 ++ site2 println( "site1 ++ site2 : " + site ) // ++ 作为方法使用 site = site1.++(site2) println( "site1.++(site2) : " + site ) } }
映射(Map)
默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类
// 空哈希表,键为字符串,值为整型 var A:Map[Char,Int] = Map() // Map 键值对演示 val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")
注意,Map的get方法返回的对象是一个Option[String],Option表示可能为None,比如key值不存在的情况,如果不为None则是Some(value)。
Scala元组(Tuple)
元组是每个元素类型可以不一样的List,最大的size是22。
val t = (1, 3.14, "Fred") val t = new Tuple3(1, 3.14, "Fred")//3是元组中元素的个数
我们可以使用 t._1 访问第一个元素, t._2 访问第二个元素,如下所示:
object Test { def main(args: Array[String]) { val t = (4,3,2,1) val sum = t._1 + t._2 + t._3 + t._4 println( "元素之和为: " + sum ) } }
类(class)
scala的类和对象与java的类和对象基本上一样。
类定义方法如下:
class Point(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy println ("x 的坐标点: " + x); println ("y 的坐标点: " + y); } }
对象的定义方法是用object关键字,和java以class名.java 命名文件不同,scala是以类名.scala命名文件。
接口(trait)
trait关键字很像java的interface,但是它能够定义某个方法的实现。
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x) }
和java一样,scala只能继承一个父类,但如果是trait就可以继承多个,继承的关键字是extends
模式匹配
scala的 x match{case:...} 对应java中的switch(x){case:...}
捕获异常
scala的异常捕获和java大致一致,只是在catch的时候使用了模式匹配的思想。
import java.io.FileReader import java.io.FileNotFoundException import java.io.IOException object Test { def main(args: Array[String]) { try { val f = new FileReader("input.txt") } catch { case ex: FileNotFoundException => { println("Missing file exception") } case ex: IOException => { println("IO Exception") } } finally { println("Exiting finally...") } } }
提取器:apply和unapply
提取器是从传递给它的对象中提取出构造该对象的参数。感觉这个玩意很鸡肋。
object Test { def main(args: Array[String]) { //下面调用apply val x = Test(5) println(x) x match { //下面unapply 被调用 case Test(num) => println(x + " 是 " + num + " 的两倍!") case _ => println("无法计算") } } def apply(x: Int) = x*2 def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None }
文件IO
scala写文件操作直接用的是java的io,读操作有自己的,总体来讲比java简单。
import java.io._ object Test { def main(args: Array[String]) { val writer = new PrintWriter(new File("test.txt" )) writer.write("菜鸟教程") writer.close() } }
从屏幕读输入
import scala.io._ object Test { def main(args: Array[String]) { print("请输入菜鸟教程官网 : " ) //2.11版本后。Console.readLine已废弃 val line = StdIn.readLine() println("谢谢,你输入的是: " + line) } }
从文件中读内容
import scala.io.Source object Test { def main(args: Array[String]) { println("文件内容为:" ) Source.fromFile("test.txt" ).foreach{ print } } }