Scala与Java的干系... 4亚洲情色图
装配Scala. 4
Scala解释器的使用... 4
声明变量... 5
数据类型与操作符... 5
函数调用与apply()函数... 5
if抒发式... 6
语句拆伙符、块抒发式... 6
输入和输出... 6
轮回... 7
高档for轮回... 7
函数的界说与调用... 8
在代码块中界说包含多行语句的函数体... 8
海选av女优递归函数与复返类型... 8
默许参数... 8
函数调用时带名参数... 9
变长参数... 9
序列看成变长参数... 9
经由... 9
lazy值... 9
极度... 10
Array. 10
ArrayBuffer. 11
遍历Array和ArrayBuffer. 11
数组常见操作... 11
使用yield和函数式编程退换数组... 12
算法案例:移除第一个负数之后的悉数负数... 12
算法案例:移除第一个负数之后的悉数负数(校正版)... 13
创建Map. 13
探询Map的元素... 13
修改Map的元素... 13
遍历Map. 14
SortedMap和LinkedHashMap. 14
Map的元素类型—Tuple. 14
界说一个粗拙的类... 14
getter与setter. 15
自界说getter与setter. 15
仅深入field的getter递次... 15
private[this]的使用... 16
Java作风的getter和setter递次... 16
支持constructor. 16
主constructor. 17
里面类... 18
object. 18
伴生对象... 19
让object接管抽象类... 19
apply递次... 19
main递次... 20
用object来竣事陈设功能... 20
extends. 21
override和super. 21
override field. 21
val、var override/竣事 def. 23
isInstanceOf和asInstanceOf. 24
getClass和classOf. 25
使用模式匹配进行类型判断... 25
protected. 25
调用父类的constructor. 26
匿名里面类... 26
抽象类... 27
抽象field. 27
将trait看成接口使用... 28
在Trait中界说具体递次... 28
在Trait中界说具体字段... 29
在Trait中界说抽象字段... 29
为实例混入trait. 29
trait调用链... 30
在trait中掩饰抽象递次... 30
羼杂使用trait的具体递次和抽象递次... 31
trait的构造机制... 31
trait field的开动化... 32
trait接管class. 33
将函数赋值给变量... 34
匿名函数... 34
高阶函数... 34
高阶函数的类型料想... 35
Scala的常用高阶函数... 35
闭包... 36
SAM退换... 36
Currying函数... 36
return到外层函数... 37
Scala的贴近体系缚构... 37
List. 37
LinkedList. 38
Set. 38
贴近的函数式编程... 38
函数式编程详细案例:统计多个文本内的单词总额... 39
模式匹配... 39
在模式匹配中使用if守卫... 40
在模式匹配中进行变量赋值... 40
对类型进行模式匹配... 40
对Array和List进行模式匹配... 41
case class与模式匹配... 41
Option与模式匹配... 42
类型参数... 42
泛型类... 42
泛型函数... 43
上畛域Bounds. 43
下畛域Bounds. 44
View Bounds. 45
Context Bounds. 46
Manifest Context Bounds. 46
协变和逆变... 47
Existential Type. 47
隐式退换... 48
使用隐式退换加强现存类型... 49
隐式退换函数作用域与导入... 49
隐式退换的发生时机... 49
隐式参数... 50
Actor. 50
Actor的创建、启动和音信收发... 50
收发case class类型的音信... 51
Actor之间彼此收发音信... 51
同步音信和Future. 52
Scala与Java的干系
Scala与Java的干系是相配雅致的!!
因为Scala是基于Java诬捏机,也即是JVM的一门编程说话。悉数Scala的代码,王人需要经过编译为字节码,然后交由Java诬捏机来运行。
是以Scala和Java是不错无缝互操作的。Scala不错任性调用Java的代码。是以Scala与Java的干系是相配相配雅致的。
装配Scala·从Scala官方网站下载,-lang.org/download/,windows版块的装配包是scala-2.11.7.msi。
·使用下载下来的装配包装配Scala。
·在PATH环境变量中,树立$SCALA_HOME/bin目次。
·在windows号令行内即可径直键入scala,通达scala号令行,进行scala编程。
Scala解释器的使用·REPL:Read(取值)-> Evaluation(求值)-> Print(打印)-> Loop(轮回)。scala解释器也被称为REPL,会快速编译scala代码为字节码,然后交给JVM来实验。
·策画抒发式:在scala>号令行内,键入scala代码,解释器会径直复返收尾给你。若是你莫得指定变量来存放这个值,那么值默许的称号为res,况且会夸耀收尾的数据类型,比如Int、Double、String等等。
·举例,输入1 + 1,会看到res0: Int = 2
·内置变量:在背面不错延续使用res这个变量,以及它存放的值。
·举例,2.0 * res0,复返res1: Double = 4.0
·举例,"Hi, " + res0,复返res2: String = Hi, 2
·自动补全:在scala>号令行内,不错使用Tab键进行自动补全。
·举例,输入res2.to,敲击Tab键,解释器会夸耀出以下选项,toCharArray,toLowerCase,toString,toUpperCase。因为此时无法判定你需要补全的是哪一个,因此会提供给你悉数的选项。
·举例,输入res2.toU,敲击Tab键,径直会给你补全为res2.toUpperCase。
声明变量·声明val变量:不错声明val变量来存放抒发式的策画收尾。
·举例,val result = 1 + 1
·后续这些常量是不错延续使用的,举例,2 * result
·然而常量声光辉,是无法改革它的值的,举例,result = 1,会复返error: reassignment to val的诞妄信息。
·声明var变量:若是要声明值不错改革的援用,不错使用var变量。
·举例,val myresult = 1,myresult = 2
·然而在scala关节中,频繁冷漠使用val,也即是常量,因此比如肖似于spark的大型复杂系统中,需要大王人的采集传输数据,若是使用var,可能会惦记值被诞妄的革新。
·在Java的大型复杂系统的假想和设立中,也使用了肖似的特点,咱们频繁会将传递给其他模块 / 组件 / 干事的对象,假想成弗成变类(Immutable Class)。在里面也会使用java的常量界说,比如final,阻遏变量的值被改革。从而普及系统的健壮性(robust,鲁棒性),和安全性。
·指定类型:不管声明val变量,如故声明var变量,王人不错手动指定其类型,若是不指定的话,scala会自动左证值,进行类型的料想。
·举例,val name: String = null
·举例,val name: Any = "leo"
·声明多个变量:不错将多个变量放在一齐进行声明。
·举例,val name1, name2:String = null
·举例,val num1, num2 = 100
数据类型与操作符·基本数据类型:Byte、Char、Short、Int、Long、Float、Double、Boolean。
·乍一看与Java的基本数据类型的包装类型疏导,然而scala莫得基本数据类型与包装类型的主张,斡旋王人是类。scala我方会厚爱基本数据类型和援用类型的退换操作。
·使用以上类型,径直就不错调用大王人的函数,举例,1.toString(),1.to(10)。
·类型的加强版类型:scala使用好多加强类给数据类型增多了上百种增强的功能或函数。
·举例,String类通过StringOps类增强了大王人的函数,"Hello".intersect(" World")。
·举例,Scala还提供了RichInt、RichDouble、RichChar等类型,RichInt就提供了to函数,1.to(10),此处Int先隐式退换为RichInt,然后再调用其to函数
·基本操作符:scala的算术操作符与java的算术操作符也莫得什么区别,比如+、-、*、/、%等,以及&、|、^、>>、<<等。
·然而,在scala中,这些操作符其实是数据类型的函数,比如1 + 1,不错写稿念1.+(1)
·举例,1.to(10),又不错写稿念1 to 10
·scala中莫得提供++、--操作符,咱们只可使用+和-,比如counter = 1,counter++是诞妄的,必须写稿念counter += 1.
函数调用与apply()函数·函数调用方式:在scala中,函数调用也很粗拙。
·举例,import scala.math._,sqrt(2),pow(2, 4),min(3, Pi)。
·不同的少许是,若是调用函数时,不需要传递参数,则scala允许调用函数时不详括号的,举例,"Hello World".distinct
·apply函数
·Scala中的apply函数是相配特殊的一种函数,在Scala的object中,不错声明apply函数。而使用“类名()”(严格来讲应该是“对象名()”)的面孔,其实即是“类名.apply()”(严格来讲应该是“对象名.apply()”)的一种缩写。频繁使用这种方式来构造类的对象,而不是使用“new 类名()”的方式。
·举例,"Hello World"(6),因为在StringOps类中有def apply(n: Int): Char的函数界说,是以"Hello World"(6),内容上是"Hello World".apply(6)的缩写。
·举例,Array(1, 2, 3, 4),内容上是用Array object的apply()函数来创建Array类的实例,也即是一个数组。
if抒发式
·if抒发式的界说:在Scala中,if抒发式是有值的,即是if或者else中临了一滑语句复返的值。
·举例,val age = 30; if (age > 18) 1 else 0
·不错将if抒发式赋予一个变量,举例,val isAdult = if (age > 18) 1 else 0
·另外一种写法,var isAdult = -1; if(age > 18) isAdult = 1 else isAdult = 0,然而频繁使用上一种写法
·if抒发式的类型料想:由于if抒发式是有值的,而if和else子句的值类型可能不同,此时if抒发式的值是什么类型呢?Scala会自动进行料想,取两个类型的大家父类型。
·举例,if(age > 18) 1 else 0,抒发式的类型是Int,因为1和0王人是Int
·举例,if(age > 18) "adult" else 0,此时if和else的值分裂是String和Int,则抒发式的值是Any,Any是String和Int的大家父类型
·若是if背面莫得跟else,则默许else的值是Unit,也用()暗示,肖似于java中的void或者null。举例,val age = 12; if(age > 18) "adult"。此时就寥落于if(age > 18) "adult" else ()。
·将if语句放在多行中:默许情况下,REPL只可解释一滑语句,然而if抒发式频繁需要放在多行。
·不错使用{}的方式,比如以下方式,或者使用:paste和ctrl+D的方式。
if(age > 18) { "adult"
} else if(age > 12) "teenager" else "children"
语句拆伙符、块抒发式·默许情况下,scala不需要语句拆伙符,默许将每一滑看成一个语句
·一滑放多条语句:若是一滑要放多条语句,则必须使用语句拆伙符
·举例,使用分号看成语句拆伙符,var a, b, c = 0; if(a < 10) { b = b + 1; c = c + 1 }
·频繁来说,关于多行语句,如故会使用花括号的方式
if(a < 10) {
b = b + 1
c = c + 1
}
·块抒发式:块抒发式,指的即是{}中的值,其中不错包含多条语句,临了一个语句的值即是块抒发式的复返值。
·举例,var d = if(a < 10) { b = b + 1; c + 1 }
输入和输出·print和println:print打印时不会加换行符,而println打印时会加一个换行符。
·举例,print("Hello World"); println("Hello World")
·printf:printf不错用于进行时势化
·举例,printf("Hi, my name is %s, I'm %d years old.\n", "Leo", 30)
·readLine: readLine允许咱们从适度台读取用户输入的数据,肖似于java中的System.in和Scanner的作用。
·详细案例:游戏厅门禁
val name = readLine("Welcome to Game House. Please tell me your name: ")
print("Thanks. Then please tell me your age: ")
val age = readInt()
if(age > 18) {
printf("Hi, %s, you are %d years old, so you are legel to come here!", name, age)
} else {
printf("Sorry, boy, %s, you are only %d years old. you are illegal to come here!", name, age)
}
轮回·while do轮回:Scala有while do轮回,基本语义与Java疏导。
var n = 10
while(n > 0) {
println(n)
n -= 1
}
·Scala莫得for轮回,只可使用while替代for轮回,或者使用通俗版的for语句
·通俗版for语句:var n = 10; for(i <- 1 to n) println(i)
·或者使用until,表式不达到上限:for(i <- 1 until n) println(i)
·也不错对字符串进行遍历,肖似于java的增强for轮回,for(c <- "Hello World") print(c)
·跳出轮回语句
·scala莫得提供肖似于java的break语句。
·然而不错使用boolean类型变量、return或者Breaks的break函数来替代使用。
import scala.util.control.Breaks._
breakable {
var n = 10
for(c <- "Hello World") {
if(n == 5) break;
print(c)
n -= 1
}
}
高档for轮回·多重for轮回:九九乘法表
for(i <- 1 to 9; j <- 1 to 9) {
if(j == 9) {
println(i * j)
} else {
print(i * j + " ")
}
}
·if守卫:取偶数
for(i <- 1 to 100 if i % 2 == 0) println(i)
·for推导式:构造贴近
for(i <- 1 to 10) yield i
函数的界说与调用
在Scala中界说函数时,需要界说函数的函数名、参数、函数体。
咱们的第一个函数如下所示:
def sayHello(name: String, age: Int) = {
if (age > 18) { printf("hi %s, you are a big boy\n", name); age }
else { printf("hi %s, you are a little boy\n", name); age
}
sayHello("leo", 30)
Scala条目必须给出悉数参数的类型,然而不一定给出函数复返值的类型,只须右侧的函数体中不包含递归的语句,Scala就不错我方左证右侧的抒发式料想出复返类型。
在代码块中界说包含多行语句的函数体单行的函数:def sayHello(name: String) = print("Hello, " + name)
若是函数体中有多行代码,则不错使用代码块的方式包裹多行代码,代码块中临了一滑的复返值即是通盘函数的复返值。与Java中不同,不是使用return复返值的。
比如如下的函数,竣事累加的功能:
def sum(n: Int) = {
var sum = 0;
for(i <- 1 to n) sum += i
sum
}
递归函数与复返类型若是在函数体内递归调用函数自己,则必须手动给出函数的复返类型。
举例,竣事经典的斐波那契数列:
9 + 8; 8 + 7 + 7 + 6; 7 + 6 + 6 + 5 + 6 + 5 + 5 + 4; ....
def fab(n: Int): Int = {
if(n <= 1) 1
else fab(n - 1) + fab(n - 2)
}
默许参数在Scala中,偶然咱们调用某些函数时,不但愿给出参数的具体值,而但愿使用参数自己默许的值,此时就界说在界说函数时使用默许参数。
def sayHello(firstName: String, middleName: String = "William", lastName: String = "Croft") = firstName + " " + middleName + " " + lastName
若是给出的参数不够,则会从左往右递次愚弄默许参数。
def sayHello(name: String, age: Int = 20) {
print("Hello, " + name + ", your age is " + age)
}
sayHello("leo")
函数调用时带名参数在调用函数时,也不错不按照函数界说的参数规则来传递参数,而是使用带名参数的方式来传递。
sayHello(firstName = "Mick", lastName = "Nina", middleName = "Jack")
还不错羼杂使用不决名参数和带名参数,然而不决名参数必须排在带名参数前边。
sayHello("Mick", lastName = "Nina", middleName = "Jack")
变长参数在Scala中,偶然咱们需要将函数界说为参数个数可变的面孔,则此时不错使用变长参数界说函数。
def sum(nums: Int*) = {
var res = 0
for (num <- nums) res += num
res
}
sum(1, 2, 3, 4, 5)
序列看成变长参数在若是思要将一个已有的序列径直调用变长参数函数,是不合的。比如val s = sum(1 to 5)。此时需要使用Scala特殊的语法将参数界说为序列,让Scala解释器唐突识别。这种语法相配灵验!一定要好好主意,在spark的源码中大王人地使用到了。
val s = sum(1 to 5: _*)
案例:使用递归函数竣事累加
def sum2(nums: Int*): Int = {
if (nums.length == 0) 0
else nums.head + sum2(nums.tail: _*)
}
经由在Scala中,界说函数时,若是函数体径直包裹在了花括号里面,而莫得使用=聚会,则函数的复返值类型即是Unit。这么的函数就被称之为经由,即经由即是莫得复返值的函数。
经由还有一种写法,即是将函数的复返值类型界说为Unit。
def sayHello(name: String) = "Hello, " + name//函数
def sayHello(name: String) { print("Hello, " + name); "Hello, " + name }//有值,但未使用=号,如故经由
def sayHello(name: String): Unit = "Hello, " + name//有值,有=号,但强制复返类型为空,则如故经由
lazy值在Scala中,提供了lazy值的特点,也即是说,若是将一个变量声明为lazy,则只好在第一次使用该变量时,变量对应的抒发式才会发生策画。这种特点关于寥落耗时的策画操作寥落灵验,比如通达文献进行IO,进行采集IO等。
import scala.io.Source._
lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
即使文献不存在,也不会报错,只好第一个使用变量时会报错,阐发了抒发式策画的lazy特点。
val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
寥落于界说了一个递次,只好在调用该递次时才会去实验递次体:
def lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
极度在Scala中,极度措置和拿获机制与Java是相配一样的。
try {
throw new IllegalArgumentException("x should not be negative")
} catch {
case _: IllegalArgumentException => println("Illegal Argument!")
} finally {
print("release resources!")
}
Import java.io._
try {
throw new IOException(“io exception!!!")
} catch {
case _: IllegalArgumentException => println("illegal argument")
}
try {
throw new IOException("user defined exception")
} catch {
case e1: IllegalArgumentException => println("illegal argument")
case e2: IOException => println("io exception")
}
Array在Scala中,Array代表的含义与Java中肖似,亦然长度弗成改革的数组。此外,由于Scala与Java王人是运行在JVM中,两边不错彼此调用,因此Scala数组的底层内容上是Java数组。举例字符串数组在底层即是Java的String[],整数数组在底层即是Java的Int[]。
// 数组开动化后,长度就固定下来了,况且元素全部左证其类型开动化
val a = new Array[Int](10)
a(0)
a(0) = 1
val a = new Array[String](10)
// 不错径直使用Array()创建数组,元素类型自动料想
val a = Array("hello", "world")
a(0) = "hi"
val a = Array("leo", 30)
ArrayBuffer在Scala中,若是需要肖似于Java中的ArrayList这种长度可变的贴近类,则不错使用ArrayBuffer。
// 若是不思每次王人使用全适度名,则不错事先导入ArrayBuffer类
import scala.collection.mutable.ArrayBuffer
// 使用ArrayBuffer()的方式不错创建一个空的ArrayBuffer
val b = ArrayBuffer[Int]()
// 使用+=操作符,不错添加一个元素,或者多个元素
// 这个语法必须要紧记在心!因为spark源码里大王人使用了这种贴近操作语法!
b += 1
b += (2, 3, 4, 5)
// 使用++=操作符,不错添加其他贴近中的悉数元素
b ++= Array(6, 7, 8, 9, 10)
// 使用trimEnd()函数,不错从尾部截断指定个数的元素
b.trimEnd(5)
// 使用insert()函数不错在指定位置插入元素
// 然而这种操作效果很低,因为需要移动指定位置后的悉数元素
b.insert(5, 6)
b.insert(6, 7, 8, 9, 10)
// 使用remove()函数不错移除指定位置的元素
b.remove(1)
b.remove(1, 3)
// Array与ArrayBuffer不错彼此进行退换
b.toArray
a.toBuffer
遍历Array和ArrayBuffer// 使用for轮回和until遍历Array / ArrayBuffer
// 使until是RichInt提供的函数
for (i <- 0 until b.length)
println(b(i))
// 最初遍历Array / ArrayBuffer
for(i <- 0 until (b.length, 2))
println(b(i))
// 从尾部遍历Array / ArrayBuffer
for(i <- (0 until b.length).reverse)
println(b(i))
// 使用“增强for轮回”遍历Array / ArrayBuffer
for (e <- b)
println(e)
数组常见操作// 数组元素乞降
val a = Array(1, 2, 3, 4, 5)
val sum = a.sum
// 赢得数组最大值
val max = a.max
// 对数组进行排序
scala.util.Sorting.quickSort(a)
// 赢得数组中悉数元素内容
a.mkString
a.mkString(", ")
a.mkString("<", ",", ">")
// toString函数
a.toString
b.toString
使用yield和函数式编程退换数组// 对Array进行退换,赢得的如故Array
val a = Array(1, 2, 3, 4, 5)
val a2 = for (ele <- a) yield ele * ele
// 对ArrayBuffer进行退换,赢得的如故ArrayBuffer
val b = ArrayBuffer[Int]()
b += (1, 2, 3, 4, 5)
val b2 = for (ele <- b) yield ele * ele
// 勾通if守卫,仅退换需要的元素
val a3 = for (ele <- if ele % 2 == 0) yield ele * ele
// 使用函数式编程退换数组(频繁使用第一种方式)
a.filter(_ % 2 == 0).map(2 * _)
a.filter { _ % 2 == 0 } map { 2 * _ }
算法案例:移除第一个负数之后的悉数负数// 构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)
// 每发现一个第一个负数之后的负数,就进行移除,性能较差,屡次移动数组
var foundFirstNegative = false
var arrayLength = a.length
var index = 0
while (index < arrayLength) {
if (a(index) >= 0) {
index += 1
} else {
if (!foundFirstNegative) { foundFirstNegative = true; index += 1 }
else { a.remove(index); arrayLength -= 1 }
}
}
算法案例:移除第一个负数之后的悉数负数(校正版)// 再行构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)
// 每纪录悉数不需要移除的元素的索引,稍后一次性移除悉数需要移除的元素
// 性能较高,数组内的元素迁徙只须实验一次即可
var foundFirstNegative = false
val keepIndexes = for (i <- 0 until
a.length if !foundFirstNegative 亚洲情色图