Spark记录-scala快速入门
1.hello world程序
object HelloWorld { def main(args: Array[String]) { println("Hello,World!") } }
注意
语句末尾的分号通常是可选的。
语句末尾的分号通常是可选的。
分号是表达式分隔符,它们是推断的。
Scala将行的结尾视为表达式的结尾,除非它可以推断表达式继续到下一行。
Scala程序处理从主方法开始,这是每个Scala程序的一个强制性部分。
主要方法未标记为静态。
主要方法是对自动实例化的单例对象的实例方法。
没有返回类型。实际上有Unit,这是类似于void,但它是由编译器推断。
我们可以通过在参数后面加一个冒号和类型来显式地指定返回类型:
def main(args: Array[String]) : Unit = { }
Scala使用def
关键字告诉编译器这是一个方法。
在Scala中没有访问级别修改器。
Scala未指定公用修饰符,因为默认访问级别为public。
Scala变量
在Scala中,有三种方法可以定义变量:val,var和延迟 val。
Scala允许您在声明它时决定变量是否是不可变的(只读)
val
使用关键字val
声明不可变变量。
这意味着它是一个不能更改的变量。
var
现在让我们声明一个可变变量。
一个可变变量用关键字var
来声明:
延迟val
延迟val变量计算一次,第一次访问变量。只有vals可以是惰性变量。
Scala 代码块
方法和变量定义可以是如下的单行:
def meth() = "Hello World"
方法和变量也可以在用大括号{}表示的代码块中定义。
代码块可以嵌套。
代码块的结果是在代码块中计算的最后一行,如以下示例所示。
object Main {
def meth1():String = {"hi"}
def meth2():String = {
val d = new java.util.Date()
d.toString()
}
def main(args: Array[String]) {
println(meth1 )
println(meth2 )
}
}
变量定义也可以是代码块。
val x3:String= { val d = new java.util.Date() d.toString() }
Scala 注释
Scala注释很像Java和C ++注释。
多行注释以/*开头,以*/结束。
/* This is a multiline comment: */
单行注释用//开头,并继续到行尾:
// This is a single line comment
在Scala中,我们可以嵌套多行注释:
/* This is an outer comment /* And this comment is nested */ Outer comment */
Scala 布尔类型
val x = !false
Scala字符类型
字符常量用单引号编写,区别于使用双引号写的字符串常量。
Scala字符串
Scala的String构建在Java的String上,并向Java的String添加了字符串插值等附加功能。
字符串插值
字符串插值是一种将字符串中的值与变量组合的机制。
Scala中的插值符号是在字符串的第一个双引号之前添加的s
前缀。
然后可以使用美元符号运算符$
引用变量。
以下代码说明了字符串插值的用法。
object Main {
def main(args: Array[String]) {
val bookTitle = "Scala" // creating a String
// String interpolation
println(s"Book Title is ${ bookTitle}" );
}
}
Scala数字类型
Scala中的数字数据类型构成了Float和Double类型以及诸如Byte,Short,Int,Long和Char等整数数据类型。
下表显示Scala的数值数据类型。
数据类型 | 描述 |
---|---|
Byte | 从-128到127范围内的整数 |
Short | 从-32768到32767范围内的整数 |
Int | 从-2147483648到2147483647范围内的整数 |
Long | 从-9223372036854775808到9223372036854775807范围内的整数 |
Float | 最大正有限浮点是3.4028235 * 1038,最小正有限非零浮点是1.40 * 10-45 |
Double | 最大正有限双是1.7976931348623157 * 10308,最小正有限非零双是4.9 * 10-324 |
例子
Scala可以按顺序自动将数字从一种类型转换为另一种类型。
Byte . Short . Int . Long . Float . Double.
其中字节类型是最低的,并且可以转换为任何其他类型,如以下示例所示:
val x: Byte = 30
我们可以将x赋值为Short类型,如下例所示:
val y: Short = x
同样,我们可以将x赋值为Int,Long,Float,Double,Scala会自动转换数字,如下例所示:
val z: Double = y
Scala不允许以前面提到的顺序自动转换。
Scala常量值
整数常量
整数常量可以用十进制,十六进制或八进制表示。
详细总结在下表中。
类型 | 格式 | 例子 |
---|---|---|
Decimal | 0或非零数字后跟零或多个数字(0-9) | 0, 1, 321 |
Hexadecimal | 0x后跟一个或多个十六进制数字(0-9,A-F,a-f) | 0xFF, 0x1a3b |
Octal | 0后跟一个或多个八进制数字(0-7)a | 013, 077 |
截至Scala 2.10,一个八进制常量已被弃用。
您可以通过在常量前添加一个-
号来表示负数。
对于长文本,需要在文本末尾附加L
或l
字符,除非将值分配给声明为Long的变量。
否则,推断Int。
整数字符串的有效值受要为其分配值的变量的类型的限制。
下表定义了包含的限制。
目标类型 | 最低(含) | 最大(包括) |
---|---|---|
Long | -263 | 263 |
Int | -231 | 231 - 1 |
Short | -215 | 215 |
Char | 0 | 216 |
Byte | -27 | 27 - 1 |
如果指定的整数常量数超出这些范围,则会发生编译时错误。
浮点常量
浮点常量是带有可选减号,零个或多个数字,后跟句点.
,后跟一个或多个数字的表达式。
对于Float
常量,在文字末尾附加F
或f
字符。否则,假定为Double。
我们可以选择为D加上D
或d
。
浮点常量可以用或不用指数表示。
指数部分的格式为e或E,后跟可选的+或 - ,后跟一个或多个数字。
这里有一些浮点常量的例子。 Double被推断除非声明的变量是Float或使用f或F后缀:
.14 3.14 3.14f 3.14F 3.14d 3.14D 3e5 3E5 3.14e+5 3.14e-5 3.14e-5 3.14e-5f 3.14e-5F 3.14e-5d 3.14e-5D
布尔常量
布尔常量是true
和false
。
它们被分配到的变量的类型将被推断为布尔值:
object Main { def main(args: Array[String]) { val b1 = true val b2 = false println(b1); println(b2); } }
字符常量
字符常量是可打印的Unicode字符或转义序列,写在单引号之间。
Unicode值介于0和255之间的字符可以由八进制转义表示,即反斜杠(\)后跟最多三个八进制字符的序列。
这里有些例子:
"A" "\u0041" // "A" in Unicode "\n" "\012" // "\n" in octal "\t"
有效的转义序列如下表所示。
序列 | 含义 |
---|---|
\b | 退格(BS) |
\t | 水平制表(HT) |
\n | 换行(LT) |
\f | 换页(FF) |
\r | 回车(CR)... |
\" | 双引号(“) |
\" | 单引号(“) |
\\ | 反斜杠(\) |
字符串常量
字符串常量是用双引号或三重双引号括起来的字符序列,即“”“...”“”。
对于双引号中的字符串字符,允许的字符与字符常量相同。
要在字符串中包含双引号“
字符,必须使用\
字符“转义"。
这里有些例子:
"This is a\ntest" "He said, \"SQL is for database!\"" "First\tSecond"
由双引号的三元组界定的字符串常量称为多行字符串常量。
这些字符串可以覆盖几行。换行符将是字符串的一部分。它们可以包括任何字符,包括一个或两个双引号在一起,但不能三个在一起。
它们对于不具有有效Unicode或转义序列的\字符的字符串非常有用。
这里有三个示例字符串:
"""This is a \ntest""" """He said, "SQL is for database!" """ """First line\n Second line\t Fourth line"""
在代码中使用多行字符串时,要使用String.stripMargin缩进子字符串以进行正确的代码格式化。
它删除子字符串中的所有空格,直到并包括垂直条|
的第一次出现。
要添加空格缩进,请将空格放在|
后面。
考虑这个例子:
object Main {
def main(args: Array[String]) {
println(hello("This is a test") );
}
def hello(name: String) = s"""Welcome!
Hello, $name!
* (Star!!)
|Hi.
| whitespace.""" .stripMargin
}
要使用不同于|
的前导字符,请使用带有Char(字符)参数的stripMargin的重载版本。
如果整个字符串都有要删除的前缀或后缀,则有相应的前缀和stripSuffix方法。
object Main {
def main(args: Array[String]) {
println(goodbye("www.w3cschool.cn"));
}
def goodbye(name: String) =
s"""xxxGoodbye, ${name}yyy
xxxCome again!yyy""" .stripPrefix("xxx").stripSuffix("yyy")
}
符号常量
Scala有符号类型,它们是内部连接的字符串,意味着具有相同“名称”的两个符号实际上是指内存中的同一个对象。
符号常量是单引号'
,后跟一个或多个数字,字母或下划线(“_”),但第一个字符不能是数字。
函数常量
(i:Int,s:String)=>
s + i 是Function2类型的函数文本[Int,String,String](返回String)。
你甚至可以使用常量语法作为类型声明。
以下声明是等效的:
val f1: (Int,String) => String = (i, s) => s+i val f2: Function2[Int,String,String] = (i, s) => s+i
元组常量
Scala库包括用于将N个项分组的TupleN类(例如,Tuple2),以及括号内的项的逗号分隔列表的文字语法。
对于1到22之间的N,有单独的TupleN类。
例如,val tup =(“Hi”,2014)定义了一个Tuple2实例,其中第一个元素推断String,第二个元素Int推断。
Tuple实例是不可变的,第一类值,因此您可以将它们分配给变量,将它们作为值传递,并从方法中返回。
我们还可以使用常量语法为Tuple类型声明:
val t1: (Int,String) = (1, "two") val t2: Tuple2[Int,String] = (1, "two")
以下示例演示使用元组:
object Main {
def main(args: Array[String]) {
val t = ("Hello", 1, 2.3)
println( "Print the whole tuple: " + t )
println( "Print the first item: " + t._1 )
println( "Print the second item: " + t._2 )
println( "Print the third item: " + t._3 )
val (t1, t2, t3) = ("World", "!", 0x22)
println( t1 + ", " + t2 + ", " + t3 )
val (t4, t5, t6) = Tuple3("World", "!", 0x22)
println( t4 + ", " + t5 + ", " + t6 )
}
}
表达式t._n从元组t中检索第n个项,从一个开始,不是零,遵循历史约定。
有几种方法来定义两元素元组,有时称为一对。
我们可以在两个值之间使用“箭头运算符”,以及在元组相关类上使用特殊的工厂方法:
(1, "one") 1 -> "one" Tuple2(1, "one")
Scala Nothing和Null类型
Null是所有引用类型的子类型。它是所有AnyRef类型的子类型,为关键字null提供类型。
Scala没有null关键字。
例如,不可能为scala.Int类型的变量分配null。
对于影响程序流程的操作,没有任何提供兼容的返回类型。
Nothing的用法之一是它发出异常终止的信号。
任何时候,如果你想使用null
,请改用Option
。
Scala选项
Option
允许我们在没有null“hack”的情况下显式地表达空值。
Option是一个抽象类,它的两个具体子类是Some,当我们有一个值,而None,当我们没有。
例子
您可以在以下示例中查看选项,一些和无操作,其中我们在美国创建州首府地图:
object Main {
def main(args: Array[String]) {
val stateCapitals = Map(
"Alabama" -> "Montgomery",
"Alaska" -> "Juneau",
"Wyoming" -> "Cheyenne")
println( "Get the capitals wrapped in Options:" )
println( "Alabama: " + stateCapitals.get("Alabama") )
println( "Wyoming: " + stateCapitals.get("Wyoming") )
println( "Unknown: " + stateCapitals.get("Unknown") )
println( "Get the capitals themselves out of the Options:" )
println( "Alabama: " + stateCapitals.get("Alabama").get )
println( "Wyoming: " + stateCapitals.get("Wyoming").getOrElse("Oops!") )
println( "Unknown: " + stateCapitals.get("Unknown").getOrElse("Oops2!") )
}
}
注意
Map.get方法返回一个Option [T]
,在这种情况下T
是String。
通过返回一个选项,我们不能“忘记”我们必须验证返回的东西。
如果Option
是Some
,则Some.get
返回值。
如果Option
实际上是None
,那么None.get
将抛出一个NoSuchElementException
异常。
在最后两个println语句中的getOrElse
返回Option
中的值,如果它是一个Some
实例,或者返回传递给getOrElse
的参数,如果它是一个None
实例。
getOrElse
参数作为默认返回值。
Scala范围
有些代码需要从一些开始到结束创建一个数字序列。一个Range
常量量是我们需要的。
范围可以通过它们的开始,结束和步进值来定义。
要在Scala中创建范围,请使用预定义的方法,如以下代码所示:
object Main { def main(args: Array[String]) { println(1 to 5 ) } }
我们还可以使用预定义的方法创建一个具有上限(不包括其上限)的范围,直到如下代码所示。
object Main { def main(args: Array[String]) { println(1 until 5 ) } }
对于1到5,创建范围(1,2,3,4,5),但对于1到5,创建具有上限独占范围(1,2,3,4)的范围。
我们还可以使用预定义的方法创建一个带有步进值的范围,如下面的代码所示。
object Main { def main(args: Array[String]) { println(1 to 20 by 4 ) } }
例子
以下示例显示如何为支持它们的类型创建范围:Int,Long,Float,Double,Char,BigInt和BigDecimal。
object Main {
def main(args: Array[String]) {
var v = 1 to 10 // Int range inclusive, interval of 1, (1 to 10)
println(v)
v = 1 until 10 // Int range exclusive, interval of 1, (1 to 9)
println(v)
val v1 = 1 to 10 by 3 // Int range inclusive, every third.
println(v1)
val v2 = 10 to 1 by -3 // Int range inclusive, every third, counting down.
println(v2)
val v3 = 1L to 10L by 3 // Long
println(v3)
val v4 = 1.1f to 10.3f by 3.1f // Float with an interval != 1
println(v4)
val v5 = 1.1f to 10.3f by 0.5f // Float with an interval < 1
println(v5)
val v6 = 1.1 to 10.3 by 3.1 // Double
println(v6)
val v7 = "a" to "g " by 3 // Char
println(v7)
val v8 = BigInt(1) to BigInt(10) by 3
println(v8)
val v9 = BigDecimal(1.1) to BigDecimal(10.3) by 3.1
println(v9)
}
}
注意
您可以创建包含或独占上限的范围,并且您可以指定不等于1的间隔:
Scala元组
元组是具有相同或不同类型的两个或更多个值的有序容器。
然而,与列表和数组不同,没有办法迭代元组中的元素。
它的目的只是作为一个多个值的容器。
元组在需要组合离散元素并提供结构化数据的通用方法时非常有用。
我们可以通过两种方式创建一个元组:
- 通过用逗号分隔的值写入值,并用一对括号括起来
- 通过使用关系运算符
->
例子
以下代码显示了一个包含Int,一个布尔值和一个String的元组,使用前一个方法。
val tuple = (1, false, "Scala")
以下代码显示了使用关系运算符创建的元组:
val tuple2 ="title" -> "Beginning Scala"
元组的单个元素可以通过其索引访问,其中第一个元素具有索引1。
以下代码显示了访问元组的第三个元素。
val tuple = (1, false, "Scala") val third = tuple._3
Scala单元类型
单元类型用于定义不返回数据的函数。它类似于Java中的void关键字。
例子
以下代码定义了具有单元类型的主方法。
def main(args: Array[String]) : Unit = { }
单元常量是一对空圆括号, ()。
附录
import org.apache.spark.SparkConf; import org.apache.spark.SparkContext; //定义一个类Person(属性,方法) class Person(val name: String, var age: Int) object base { //定义一个无返回值的方法 def func(s:String):Unit={ println(s) } def meth() = "Hello World" //单行方法代码块 def meth1():String = {"hi"} //返回值为String的方法代码块 def meth2():String = { //具体的函数体实现(代码块) val d = new java.util.Date() d.toString() } //删除前缀和后缀 def goodbye(name: String) = s"""xxxGoodbye, ${name}yyy xxxCome again!yyy""" .stripPrefix("xxx").stripSuffix("yyy") //主方法:Unit相当于void,无返回值类型 def main(args: Array[String]): Unit = { //System.setProperty("hadoop.home.dir", "D:\\hadoop");//设置hadoop环境 //val conf = new SparkConf().setAppName("Base").setMaster("spark://192.168.66.66:7077");//加载spark远程作业调度 //val spark=new SparkContext(conf);//声明一个sparkContext上下文 val data = Array(1, 2, 3, 4, 5); //定义一个不可变数组 func("hello");//调用方法 println(data(1))//输出单个数组元素 //遍历输出data数组 for (i<-data) { println(i) } //spark.stop(); for(i<- 1 to 10){ println(i) } for { i <- 1 to 10 j <- 1 to 10 } println(i* j) val p = new Person("Dean Wampler", 29) //声明一个类对象 println(p.name) //调用并输出类属性 println(p.age ) p.age = 30 println(p.age ) println(meth+"\n"+meth1()+"\n"+meth2())//函数调用无参数不需要带() /*定义一个不可变且返回值为String的代码块*/ val x3:String= { val d = new java.util.Date() d.toString() } println(x3) val x = !false //布尔类型 var xf=true //布尔型常量 val y='1' //单引号的字符常量 val z="scala" //双引号的字符串常量 val zx:String="spark" println(xf+""+x+"-"+y+s"-${z}"+"-"+zx) //s"-${z}"字符串插值 val xx: Byte = 30 //数字类型Byte . Short . Int . Long . Float . Double. val yy: Short = xx val zz: Double = yy println(xx+"-"+yy+"-"+zz) println(goodbye("www.w3cschool.cn")); //函数常量定义 val f1: (Int,String) => String = (i, s) => s+i //返回值为String val f2: Function2[Int,String,String] = (i, s) => s+i //前两个为参数,后一个为返回值 println(f1(1,"name")+"-"+f2(1,"siat")) //元组常量 //val t1: (Int,String) = (1, "two") //val t2: Tuple2[Int,String] = (1, "two") val t = ("Hello", 1, 2.3) //定义一个元组 println( "Print the whole tuple: " + t ) //输出整个元组 println( "Print the first item: " + t._1 ) //输出第一个元组元素 println( "Print the second item: " + t._2 ) //输出第二个元组元素 println( "Print the third item: " + t._3 ) //输出第三个元组元素 //定义三个元组,每个元组存储一个元素 val (t1, t2, t3) = ("World", "!", 0x22) println( t1 + ", " + t2 + ", " + t3 ) val (t4, t5, t6) = Tuple3("World", "!", 0x22) println( t4 + ", " + t5 + ", " + t6 ) //Scala没有null关键字 //范围Range println(1 to 5 ) //包括上限1,2,3,4,5 println(1 until 5 ) //不包括上限1,2,3,4 println(1 to 20 by 4 ) //从1到20每次进四个值包括下限1 val v2 = 10 to 1 by -3 //Int val v3 = 1L to 10L by 3 //Long val v4 = 1.1f to 10.3f by 3.1f //Float val v5 = 1.1f to 10.3f by 0.5f val v6 = 1.1 to 10.3 by 3.1 //Double val v7 = 'a' to 'g' by 3 //Char val v8 = BigInt(1) to BigInt(10) by 3 val v9 = BigDecimal(1.1) to BigDecimal(10.3) by 3.1 println(v2+"-"+v3+"-"+v4+""+v5+""+v6+""+v7+""+v8+""+v9) val tuple = (1, false, "Scala") val tuple2 ="title" -> "Beginning Scala" val third = tuple._3 println(tuple._2+"-"+tuple2._1+"-"+third) //Unit单元类型用于定义不返回数据的函数。它类似于Java中的void关键字。 } }