Spark记录-scala快速入门

时间:2023-02-04 23:13:01

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,一个八进制常量已被弃用。

您可以通过在常量前添加一个-号来表示负数。

对于长文本,需要在文本末尾附加Ll字符,除非将值分配给声明为Long的变量。 

否则,推断Int。

整数字符串的有效值受要为其分配值的变量的类型的限制。

下表定义了包含的限制。

目标类型 最低(含) 最大(包括)
Long -263 263
Int -231 231 - 1
Short -215 215
Char 0 216
Byte -27 2- 1

如果指定的整数常量数超出这些范围,则会发生编译时错误。

浮点常量

浮点常量是带有可选减号,零个或多个数字,后跟句点.,后跟一个或多个数字的表达式。

对于Float常量,在文字末尾附加Ff字符。否则,假定为Double。

我们可以选择为D加上Dd

浮点常量可以用或不用指数表示。

指数部分的格式为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

布尔常量

布尔常量是truefalse

它们被分配到的变量的类型将被推断为布尔值:

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。

通过返回一个选项,我们不能“忘记”我们必须验证返回的东西。

如果OptionSome,则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关键字。
}
}