@wuzhimang
2017-08-12T15:49:43.000000Z
字数 9816
阅读 1769
博客
博客链接: http://codeshold.me/2017/07/scala_tour_note.html
因实习,需要了解数据分析方面的知识,需要学习Spark、Scala,花了一天的时间过了一下scala教程(总结即是本文),但个人推荐先从《快学Scala+中文版》这本书开始看(正在看...)这个更适合入门…… 无奈自己后知后觉了……
Tour 学习链接(自己主要是看中文):
1. TOUR OF SCALA (scala-lang.org)
2. Scala教程 (runoob.com)
def main(args: Array[String]), Scala程序从main()方法开始处理Scala 使用 package 关键字定义包, 将代码定义到某个包中有两种方式
package com.swfclass HelloWorld------------------------package com.swf {class HelloWorld}
Scala 使用 import 关键字引用包。默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,这里也能解释,为什么以scala开头的包,在使用时都是省去scala。
import java.awt.Color // import Colorimport java.awt._ // import all the membersimport java.awt.{Font, Color} // import members via selector 选择器import java.until.{HashMap => JavaHashMap} // rename membersimport java.util.{HashMap => _, _} // 引入util包的所有成员,但是HashMap被隐藏def handle(evt: event.ActionEvent) {Color.}
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()Nothing 类型在Scala的类层级的最低端;它是任何其他类型的子类型。Any 是所有其他类的超类AnyRef 类是Scala里所有引用类(reference class)的基类字面量 进一步了解
0.0, 0f, 1.0e100true, false'<标识符>这种字面量被映射成预定义类scala.Symbol的实例, 符号字面量除了显示名字之外,什么都不能做'\n', "hello", """hello""" 字符、字符串、多行字符 scala.Null 类型。 scala.Null和scala.Nothing是用统一的方式处理Scala面向对象类型系统的某些"边界情况"的特殊类型。Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。
val myVal : String = "Foo" // 申明常量,值不能修改var myVar : String = "Foo" // 申请变量,值可以修改// 变量类型申明var VariableName : DataType [= Initial Value]val VariableName : DataType [= Initial Value]// 变量类型引用var myVar = 10val myVal = "hello, scala!"// 多变量申明val xmax, ymax = 100val pa = (40, "Foo")--------scala> val x, y = 1, 2 // 和python不同 !!!!!!<console>:1: error: ';' expected but ',' found.val x, y = 1, 2^scala> val x, y = (1, 2)x: (Int, Int) = (1,2)y: (Int, Int) = (1,2)scala> val x, y = 1x: Int = 1y: Int = 1
Scala 访问修饰符基本和Java的一样,分别有:private,protected,public
private[x], protected[x] 这里的x指代某个所属的包、类或单例对象。如果写成private[x],读作"这个成员除了对[…]中的类(或[…]中的包中的类)及它们的伴生对象可见外,对其它所有类都是private。
package bobsrockets{package navigation{private[bobsrockets] class Navigator{ // 对bobsrockets中的对象都可见,其他则是privateprotected[navigation] def useStarChart(){class LegOfJourney{private[Navigator] val distance = 100}private[this] var speed = 200}package launch{import navigation._ // import all membersobject Vehicle{private[launch] val guide = new Navigator}}}}}
运算符
scala> -8 >>> 1 // 无符号右移!!! 多了个这个res6: Int = 2147483644scala> 8 >>> 1res7: Int = 4
控制语句
if(...){...}else if(){...}else{...}while(...){...};, do{...}while(...);, for(...){...}<- 用于为变量赋值, to, until, if, yield
object Test {def main(args: Array[String]) {var a = 0;val numList = List(1, 2, 3, 4, 5, 6, 7)for ( a <- 1 to 10 ) {}for ( a <- 1 to 3; b <- 1 to 3) {}for ( a <- 1 until 10 ) { //不包含10}for ( a <- numList ) { // 循环集合}for ( a <- numList if a != 3; if a < 8 ) { // 循环中的过滤println("Value of a :" + a)}// 可以将for循环中的返回值作为一个变量存储var retVal = for{ a <- numList if a != 3; if a < 8 } yield afor( a <- retVal ) {println("!!!value of a :" + a)}}}
基本概念
def functionName([para list]) : [return type] = { function body; return [expr] } , 如果不写=和方法的主体,则方法会被隐世的声明为抽象,包含它的类型于是也是一个抽象类型
object add {def addInt( a:Int, b:Int ) : Int = {var sum:Int = 0sum = a + breturn sum}def printMe() : Unit = {println("hello world!")}}
函数概念解析 runnob.com
传名调用(call-by-name): Scala解释器支持两种--call-by-value和call-by-name
object Test {def main(args: Array[String]) {println(delay(time()))}def time() = {println("richie")}def delay(t: => Long) = { // => 设置传名调用 (放在变量名和变量类型中间)println("wfshi")t}
指定函数参数名, 可变参数, 默认参数, 递归, 嵌套
object Test {def main(args: Array[String]) {printInt(b=5, a=3) // 制定参数名printStrings("richie", "wf", "shi")println("F(5)" + factorial(5))println("addInt" + addInt())}def printInt(a: Int, b: Int) {println("Value of a :" + a)}// 可变参数def printStrings(args: Sting*) = {var i: Int = 0for(arg <- args) {println("Arg value" + i + arg)i += 1}}// 递归def factorial(n: BigInt): BigInt = {if (n <= 1)1 // 无returnelsen * factorial(n-1)}// 默认参数值def addInt(a:Int = 5, b:Int = 7) : Int = {var sum:Int = 0sum = a + breturn sum}// 函数嵌套def factorial(i: Int) {def fact(i: Int, accumulator: Int): Int = {if (i <= 1)accumulator // 无returnelsefact(i-1, i*accumulator)}fact(i, 1)}
匿名函数
// 匿名函数var inc = (x:Int) => x+1 // 下面的简写def add2 = new Function1[Int,Int] {def apply(x:Int):Int = x+1}var x = inc(7)-1// 可定义多个函数var mul = (x: Int, y: Int) => x*y// 可以不设置参数var userDir = () => {System.getProperty("user.dir")}
高阶函数: higher-order function 操作其他函数的函数; 匿名函数
object Test{def main(args: Array[String]){println(apply(layout, 10))}// 函数 f 和 值 v 作为参数,而函数 f 又调用了参数 vdef apply(f: Int => String, v: Int) = f(v)def layout[A](x: A) = "[" + x.toString() + "]"
偏应用函数: 一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
import java.util.Dateobject Test{def main(args: Array[String]) {val date = new Date// 下划线替换缺失的参数列表, 并把这新的函数值的索引赋值给变量val logWriteDataBound = log(date, _: String)logWithDateBound("message1")logWithDateBound("message2")}def log(data: Date, message: String) = {println(date + "----" + mesage)}
currying 函数科里化: 将原来接受两个参数的函数变成新的接受一个参数的函数的过程
def add(x:Int, y:Int) = x+ydef add(x:Int)(y:Int) = x+y // currying, (y:Int)=>1+y
闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。
object Test {def main(args: Array:[String]) {println("muliplier(1) value = " + multiplier(1))println("muliplier(2) value = " + multiplier(2))}var factor = 3val multiplier = (i:Int) => i * factor // 定义了一个匿名函数,并赋值给multiplier
val greeting:String = "Hello World!"; // 不可变val buf = new StringBuilder; buf += 'a'; // 可变"a".length"a".length()"a".concat("b")"a" + "b"printf("%s %d"...) // 格式化输出
数组 常用方法
var z:Array[String] = new Array[String](3)var z = new Array[String](3)z(0) = "richiewfshi"; z(1) = "richie"; z(2) = "wfshi"var z = Array("richie", "wf", "shi")z.length// 多维数组var richieMatrix = ofDim[Int](3,3)richieMatrix(i)(j) = "xx"var my = concat(mylist1, mylist2)import Array._var mylist3 = range(1, 100, 50)// 使用数组方式之前需要 import Array._
集合操作
针对不可变集合类的每次操作都会返回一个新的集合,同时使原来的集合不发生改变
val x = List(1, 2, 3, 4)val x = Set(1, 3, 5, 7)val x = Map("one" -> 1, "two" -> 2, "three" -> 3) // !!!scala> val mymap = {"key1" -> 1; "key2" -> 2}mymap: (String, Int) = (key2,2)val t = new Tuple3(1, 3.14, "richie") //Tuple3[Int, Int, String]类型,支持的元组最大长度为22val t = (1, 3, "wfs")// Tuple.productIterator() 迭代输出元组的所有元素t.productIterator.foreach(i => println("Value = " + i)(1, 2, "swf").toString // Tuple.toString() 将元素组合成一个字符串(1, 2).swapval sum = x._1 + x._2val x:Option[Int] = Some(5) // 定义Option, Option[T] 表示有可能包含值的容器,也可能不包含值。
迭代器
Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。常用方法
val it = Iterator("richie", "wf", "shi") // 用于检测集合中是否还有元素。while(it.hasNext) {println(it.next()) // 返回迭代器的下一个元素,并且更新迭代器的状态。}val itmax = it.maxval itmin = it.minval itlen = it.lengthval itsize = it.size
Option
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。常用方法
val myMap: Map[String, String] = Map("key1" -> "value")val value1: Option[String] = myMap.get("key1") // Some("value")val value2: Option[String] = myMap.get("key2") // None// 通过模式匹配来输出匹配值val res = show(myMap.get("key1"))def show(x: Option[String]) = x match {case Some(s) => scase None => "?"}val a:Option[Int] = Some(5)val b:Option[Int] = Noneb.getOrElse(0); b.getOrElse(5) // 都返回默认值5a.isEmpty
类和对象
Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:
class Location(override val xc: Int, override val yc: Int,val zc: Int) extends Point(xc, yc) {...}// Scala重写一个非抽象方法,必须用override修饰符class Employee extends Person {var salary = 0.0override def toString = super.toString + "[salary=" + salary + "]"}
Trait(特征)
Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承
trait Equal {def isEqual(x: Any): Booleandef isNotEqual(x: Any): Boolean = !isEqual(x)}class Point(xc: Int, yc: Int) extends Equal {var x: Int = xcvar y: Int = ycdef isEqual(obj: Any) =obj.isInstanceOf[Point] &&obj.asInstanceOf[Point].x == x}object Test {def main(args: Array[String]) {val p1 = new Point(2, 3)val p2 = new Point(2, 4)println(p1.isNotEqual(p2))}}
提取器是从传递给它的对象中提取出构造该对象的参数。
=> 隔开了模式和表达式。使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配
def matchT(x: Int): Int = x match {case 1 => "one"case 2 => "two"}def matchTest(x: Any): Any = x match {case 1 => "one"case "two" => 2case y: Int => "scala.Int"case _ => "many"}val alice = new Person("Alice", 25)for(person <- List(alice, bob, charlie)) {person match {case Person("Alice", 25) => println("Hi Alice")case Person("Bob", 25) => println("Hi Bob")}}// 样例类case class Person(name: String, age: Int)
正则表达式 实例参考
import scala.util.matching.Regexobject Test{def main(args: Array[String]) {// val pattern = "scala".rval pattern = new Regex("(S|s)cala")val str = "scala is Scalable and Cool"println((pattern findFirstIn str).mkString(",")) //使用逗号,连接返回结果
文件写操作,直接使用java中的I/O类
import java.io._object Test {def main(args: Array[String]) {val writer = new PrintWriter(new File("test.txt"))writer.write("richiewfshi")writer.close()}}
屏幕上读取用户输入
object Test {def mian(args: Array[String]) {val line = Console.readLineprintln("richie" + line)
文件读操作
import scala.io.Sourceobject Test {def main(args: Array[String]) {Source.fromFile("richie").foreach{}}}
throw new IllegalArgumentException 抛出异常
在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case字句
import java.io.FileReaderimport java.io.FileNotFoundExceptionimport java.io.IOExceptionobject Test {def main(args: Array[String]) {try {val f = new FileReader("input.txt")} catch {case ex: FileNotFoundException => {println("Missing file execption")}case ex: IOException => {println("IO Exception")}} finally { // 都需要执行println("Existing finally...")}