转载请注明joymufeng,欢迎访问 (http://www.playscala.cn)
原文链接:
3.1 String
在Scala中,String更加方便好用:
//原始字符串一对三引号"""括起来,可包含多行字符串,内容不需要转义"""Welcome here. Type "HELP" for help!""" //类型转换"100.0".toDouble//判断字符串相等直接用"==",而不需要使用equals方法val s1 = new String("a")s1 == "a" // true//字符串去重"aabbcc".distinct // "abc"//取前n个字符,如果n大于字符串长度返回原字符串"abcd".take(10) // "abcd"//字符串排序"bcad".sorted // "abcd"//过滤特定字符"bcad".filter(_ != 'a') // "bcd"//字符串插值, 以s开头的字符串内部可以直接插入变量,方便字符串构造val i = 100s"i=${i}" // "i=100"
Scala中没有受检异常(checked exception),所以你没有必要声明受检异常,如果真的发生异常,则会在运行时抛出。
3.2 Option
Scala用Option类型表示一个值是否存在,用来避免Java的NullPointerException。它有两个子类:Some和None。Some类型表示值存在,None类型则表示值不存在。 常用操作:
val opt: Option[String] = Some("hello")//判断是否为Noneopt.isEmpty // false//如果为None,则返回默认值"default",否则返回opt持有的值opt.getOrElse("default") //如果为None则返回"DEFAULT",否则将字符转为大写opt.fold("DEFAULT"){ value => value.toUpperCase } // "HELLO"//功能同上opt match { case Some(v) => v.toUpperCase case None => "DEFAULT"}
3.3 List
在Scala中,List要么是Nil(空列表),要么就是由head和tail组成的递归结构。 head是首元素,tail是剩下的List。所以你可以这样构建List:
val list = 1 :: Nil // 等价于:val list = List(1)
连续的两个冒号"::"就像是胶水,将List的head和tail粘在一起。 常用操作:
val list = List(1, 3, 2)//获取第1个元素list.headOption.getOrElse(0) // 1//查找list.find(_ % 2 == 0).getOrElse(0) // 2//过滤list.filter(_ % 2 == 1) // List(1, 3)//排序list.sorted // List(1, 2, 3)//最小值/最大值/求和list.min // 1list.max // 3list.sum // 6//转化成字符串list.mkString(",") // "1, 3, 2"
Scala提供的List基本可以实现SQL查询的所有功能,这也是Spark为什么基于Scala开发的原因。更多功能请参考。
在Scala中默认的集合类例如List,Set,Map,Tuple等都是不可变的,所以调用其修改方法会返回一个新的实例。如果要使用可变集合,请使用scala.collection.mutable
包下相应的类。不可变类型在编写并发代码时很有用。
3.4 Tuple
Tuple(元组)Tuple可以容纳不同类型的元素,最简单的形态是二元组,即由两个元素构成的Tuple, 可以使用_1, _2等方法访问其元素:
val t = ("a", 1) // 等价于:val t: Tuple2[String, Int] = ("a", 1)t._1 // "a"t._2 // 1
也可以使用模式匹配利用Tuple同时初始化一组变量:
val t = ("a", 1)val (v1, v2) = tv1 // "a"v2 // 1
3.5 Map
Map其实是二元组的集合:
val map = Map("a" -> 1, "b" -> 2)
"->"其实是String类型上的方法,返回一个二元组:
"a" -> 1 //等价于: ("a", 1)
所以你也可以这样构建Map:
val map = Map(("a", 1), ("b", 2))
常用操作:
val map = Map("a" -> 1, "b" -> 2)//读取map("a") // 1//写入或添加键值map("a") = 0//删除键值map - "a" // Map(b -> 2)
3.6 Future
Future和Promise是Scala提供的最吸引人的特性之一,借助Future和Promise你可以轻松地编写完全异步非阻塞的代码,这在多处理器时代显得格外重要。
Future用于获取异步任务的返回结果。Future有两种状态:完成(completed)和未完成(not completed)。处于完成状态的Future可能包含两种情况的信息,一种是异步任务执行成功了,Future中包含异步任务执行成功的返回结果;另一种是异步任务执行失败了,Future中包含了相应的Exception信息。Future的独特之处在于它的值只能被写入一次,之后就会变为一个不可变值,其中包含成功或失败信息。你可以在Future上注册一个回调函数,以便在任务执行完成后得到通知:
import scala.concurrent.ExecutionContext.Implicits.globalval f = Future{ 1 + 2 }f.onComplete{ t => t match{ case Success(v) => println("success: " + v) case Failure(t) => println("failed: " + t.getMessage) }}//等待任务结束Await.ready(f, 10 seconds)
onComplete方法接受一个一元函数,类型为:Try[T] => U
。Try类型和Option类型很像,也有两个子类Success
和Failure
,前者表示任务执行成功,后者表示任务执行失败。
第1行import语句导入了一个隐式的ExecutionContext,你可以把它理解成是一个线程池,Future类在需要时会自动使用其上的线程。在Scala中你不需要直接和线程打交道。
由于Future也是一个容器类,所以可以使用for语句取回它的值:
val f = Future{ 1 + 2 }for(v <- f) { println(v) // 3}
也可以使用map方法对任务结果进行转换:
val f1 = Future{ 1 + 2 }val f2 = f1.map(v => v % 2)for(v <- f2) { println(v) // 1}
利用for语句可以等待多个Future的返回结果:
val f1 = Future{ 1 + 2 }val f2 = Future{ 3 + 4 }for{ v1 <- f1 v2 <- f2} { println(v1 + v2) // 10}
结合yield可以返回一个新的Future:
val f1 = Future{ 1 + 2 }val f2 = Future{ 3 + 4 }val f3 = for { v1 <- f1 v2 <- f2 } yield { v1 + v2 }
3.7 Promise
有时我们需要精细地控制Future的完成时机和返回结果,也就是说我们需要一个控制Future的开关,没错,这个开关就是Promise。每个Promise实例都会有一个唯一的Future与之相关联:
val p = Promise[Int]()val f = p.futurefor (v <- f) { println(v) }//3秒钟之后返回3Thread.sleep(3000)p.success(3)//等待任务结束Await.ready(f, 10 seconds)