快学scala
scala
1. scala的由来
scala是一门多范式的编程语言,一种类似java的编程语言[2] ,设计初衷是要集成面向对象编程和函数式编程的各种特性。
java和c++的进化速度已经大不如从前,那么乐于使用更现代的语言特性的程序员们正在将眼光移向他处。scala是一个很有吸引力的选择;事实上,在我看来,对于想要突破和超越java或者c++的程序员而言,scala是最具吸引力的一个。scala的语法十分简洁,相比java的样板代码,scala让人耳目一新。scala运行于java虚拟机之上,让我们可以使用现成的海量类库和工具。他在拥抱函数式编程的同时,并没有非其面向对象,使你得以逐步了解和学习一种全新的编程范式。scala解释器可以让你快速运行试验代码,这使得学习scala的过程颇为轻松惬意。最后,同时也是很重要的一点,scala是静态类型的,编译器能够帮助我们找到大部分错误,避免时间的浪费。
2. scala基础
2.1. scala环境变量安装
见安装文档
2.2. 认识scala
打开cmd,输入scala
2.3. 安装scala-eclipse
2.3.1. 安装
将scala-SDK-3.0.1-vfinal-2.10-win32.win32.x86_64.zip解压到任意目录即可
2.3.2. 打开
2.3.3. 创建scala工程
点击finish
2.3.4. 创建scala包
2.3.5. 创建scala类
2.4. 创建变量
Scala 定义了两种类型的变量 val 和 var ,val 类似于Java中的final 变量,一旦初始化之后,不可以重新赋值(我们可以称它为常变量)。而var 类似于一般的非final变量。可以任意重新赋值。
2.4.1. 不指定类型
package org.apache.first object test { def main(args: Array[String]): Unit = { valmyint = 1 valmystring ="string" varmyint2 = 1 varmystring2 ="string" println(myint) println(mystring) println(myint2) println(mystring2) } } |
你可能注意到了,在变量声明和赋值语句之后,我们并没有使用分号。在scala中,仅当同一行代码中存在多条语句时采用分号隔开,但是其余情况你也可以像java那样使用分号,也不会报错。
2.4.2. 指定类型
当然如果你愿意,你也可以采用和Java一样的方法,明确指定变量的类型,如
valmyint:Int = 1;
valmystring:String =null;
2.4.3. 常用变量
和java一样,scala也有7中数据类型:Byte,Char,Short,Int,Long,Float和Double,以及一个Boolean类型。跟java不同的是,这些类型是类。scala不刻意区分基本数据类型和引用数据类型。你可以对数字执行方法,例如:
1.toString(); //产生字符串“1”
或者,更有意思的是,你可以:
1.to(10) //产生Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),类似数组
并通过1.to(10)(5)获取其中的值
2.5. 算数和操作符重载
在scala中,+-*%等操作符完成的是和java一样的工作,位操作符&|^>><<也是一样。只有一点特殊的区别:这些操作符实际上是方法。例如:
a+b
是如下调用的简写:
a.+(b)
这里的+就是方法名。
和java和c++相比,scala有一个显著的不同,scala并没有提供++和—的操作。
2.6. 定义函数
Scala既是面向对象的编程语言,也是面向函数的编程语言,因此函数在Scala语言中的地位和类是同等第一位的。下面的代码定义了一个简单的无返回值和有返回值的代码:
2.6.1. 空参无返回值
def main(args: Array[String]): Unit = {
option()
}
def option(): Unit = {
println("ok")
}
option函数的返回值类型为Unit 表示该函数不返回任何有意义的值,Unit类似于Java中的void类型
2.6.2. 空参有返回值
def main(args: Array[String]): Unit = {
valreturnval = option()
println(returnval);
}
defoption(): Int = {
}
2.6.3. 有参数有返回值
def main(args: Array[String]): Unit = {
valreturnval = option(3,5)
println(returnval);
}
def option(x:Int,y:Int): Int = {
if (x >y) x
else
y
}
Scala函数以def定义,然后是函数的名称(如option),然后是以逗号分隔的参数。Scala中变量类型是放在参数和变量的后面,以“:”隔开。同样如果函数需要返回值,它的类型也是定义在参数的后面(实际上每个Scala函数都有返回值,只是有些返回值类型为Unit,类似为void类型)。
此外每个Scala表达式都有返回结果(这一点和Java,C#等语言不同),比如Scala的 if else 语句也是有返回值的,因此函数返回结果无需使用return语句。实际上在Scala代码应当尽量避免使用return语句。函数的最后一个表达式的值就可以作为函数的结果作为返回值。
同样由于Scala的”type inference”特点,本例其实无需指定返回值的类型。对于大多数函数Scala都可以推测出函数返回值的类型,但目前来说回溯函数(函数调用自身)还是需要指明返回结果类型的。
3. 控制结构和函数
3.1. 条件表达式if else
scala的if/else语法结构和java一样。不过,在scala中if/else表达式有值,这个值就跟在if或者else之后的表达式值。例如:
if(x>0) 1 else -1
上述表达式的值是1或者-1.
也可以将表达式的值赋予其他变量
val s = if (x>0) 1 else -1
这个语句的写法也可以为:
val x = 0
var s =0
if (x>0) {
s=1
}else{
s=2
}
3.2. 语句终止
在java中,每个语句都以分号结束。而在scala中,与js脚本语言类似,行尾不需要分号。同样,在}和else以及类似的位置也不需要写分号,但是如果你倾向与使用分号,用就是了,他没啥坏处。
3.3. 块表达式和赋值
在java中,块语句使用一个包在{}中的语句序列。每当你需要在逻辑分支或者循环中放置多个动作时,你可以使用块语句。
在scala中,{}块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。
例如:
package org.apache.first
import scala.math._
object test {
def main(args: Array[String]): Unit = {
val test = {
val dx = 0;
val dy = 10;
min(dx,dy);
}
println(test)
}
3.4. 循环
3.4.1. while循环
object test {
def main(args: Array[String]): Unit = {
varn = 10;
while(n>0){
println(n)
n-=1;
}
}
3.4.2. for
def main(args: Array[String]): Unit = {
for(i <- 1 to 10){
println(i)
}
}
注:1 to 10,返回数字1到数字10,含头含尾。
退出循环
import scala.util.control.Breaks._
object test {
def main(args: Array[String]): Unit = {
for(i <- 1 to 10){
if(i==3) return;
println(i)
}
}
在这里,控制权的转移是通过抛出和捕获异常完成的,因此,如果时间很重要的话,尽量避免使用。
3.4.3. 高级for循环
object test {
def main(args: Array[String]): Unit = {
for(i <- 1 to 10;j <- 1 to 3){
println(i+j)
}
}
objecttest {
def main(args: Array[String]): Unit = {
for(i <- 1 to 10;j <- 1 to 3ifi == j){
println(i+j)
}
}
3.5. 函数
3.5.1. 默认参数
object test {
defmain(args: Array[String]): Unit = {
valaa = option(2);
println(aa);
}
def option(x:Int,y:Int=1): Int = {
if (x >y) x
else
y
}
}
option函数有两个参数,但是y这个参数是带默认值的,所以,如果你只传一个参数x,那么y就会走默认值。
3.5.2. 变长参数
objecttest {
def main(args: Array[String]): Unit = {
option(2,3,4,5,6);
}
def option(args:Int*): Unit = {
println(args(3))
for(arg <- args){
println(arg);
}
}
}
3.5.3. 递归
object test {
def main(args: Array[String]): Unit = {
varaa = option(2,3,4,5,6);
println(aa)
}
def option(args:Int*): Int = {
if(args.length==0){
0
}else{
args.head + option(args.tail: _*)
}
}
}
在这里,args.head是args的首个元素,而tail是所有其他的参数序列,_*是将args.tail转换成一个序列。类似于js的eval()。
3.6. 过程
scala对于不返回值的函数有特殊的表示法。如果函数体包含在花括号当中,但是没有等号“=”,那么返回值类型就是Uint。这样的函数被称为过程(procedure)。过程不返回任何值。
object test {
def main(args: Array[String]): Unit = {
option(2);
}
def option(x:Int) = {
println(x+5)
}
}
也可以声明Unit返回值。
3.7. 懒值
当val被声明为lazy时,它的初始化将被推迟,知道我们首次对它取值。例如:
def main(args: Array[String]): Unit = {
lazyvalwords = scala.io.Source.fromFile("/usr/local/a.txt").mkString;
//println(words);
}
如果不访问words,那么文件不会被打开,但是去掉lazy或者访问words的时候,就会报错。
3.8. 异常
scala的异常工作机制和java的一样。当你抛出异常时,比如:
throw new IllegalArgumentException("aaa");
当前的运算被中止。不过与java不同的是,scala不需要声明函数会抛出哪种异常。
try{
}catch{
}finally{
}
4. 数组及操作
4.1. 定长数组
//3个整数的数据,所有元素为0
val arr1 = new Array[Int](3)
val arr2 = Array(0, 0, 0)
val arr3 = Array("hadoop", "spark")
//取值、赋值
val str = arr3(1)
arr3(1) = "storm"
4.2. 变长数组
ArrayBuffer类似Java中的ArrayList
val a = ArrayBuffer[Int]()
或val a = new ArrayBuffer[Int]
a +=1 //在尾端添加元素
a +=(1,2,3) //追加多个元素
a ++= ArrayBuffer(7,8,9) //追加集合
a.trimEnd(2) //移除最好两个元素
a.insert(2, 6, 7) //在下标2之前插入6,7
a.remove(2, 2) //从下标2开始移除2个元素
val b = a.toArray //转变成定长数据组
b.toBuffer //转变成变长数据组
4.3. 遍历数组
val arr = Array(1,2,3,4,5)
//带下标的for循环
for (i <- (0 until (arr.length, 2)).reverse) { println(arr(i))
}
//增强for循环
for (i <- arr) println(i)
4.4. 数组转换
转换动作不会修改原始数组,而是产生一个全新的数组
val arr = Array(1,2,3,4,5,6,7,8,9,10)
for(e <- arr) yield e //生成一个与arr一样的
for(e <- arr if e % 2 == 0) yield e * 2
//思考:如何变得跟简单
4.5. 数组的常用算法
val arr = Array(4,3,5,1,2)
val res = arr.sum
Array("spark","hadoop", "storm").min
val b = arr.sorted
val c = arr.sortWith(_>_)
val d = arr.count(_>2)
5. 映射
val map = Map("a"->1, "b"->2, "c"->3)
或 val map = Map(("a",1), ("b",2), ("c",3))
//取值、赋值
map("a")
map.getOrElse("d", 0)
map("b") = 22
map += ("e"->8, "f"->9)
map -= ("f")
//迭代
for((k,v) <- map)
//交换k,v
for((k,v) <- map) yield (v,k)
//keySet和values
6. 元祖
元组是不同类型元素的集合
val t = ("hadoop", 1000, "spark")
val a = t._3 //元组中的下标是从1开始
"NewYork".partition(_.isUpper)
7. 复杂的集合操作方法
7.1.1. map
讲数组中的值取出来
val a = Array(6,7,8,9)
计算:
a.map(_*2)// Array[Int] = Array(12, 14, 16, 18)
数组转成Array(tuple):
map((_,1))// Array((6,1), (7,1), (8,1), (9,1))
val map = Map("a"->1, "b"->2, "c"->3)
map.map(x=>x._1)//取出map的第一个值
map.map(x=>(x._1,x._2))//取出map的所有值
7.1.2. flatten
把数组压平
语法:
val a = Array(Array(6,7,8,9), Array(10,11,12,13,14))
val res = a.faltten// val a = Array(Array(6,7,8,9), Array(10,11,12,13,14))
7.1.3. groupby
分组
val map = Map("a"->1, "b"->2, "c"->3)
按照key分组:map.groupBy(_._1)
结果:Map(b -> Map(b -> 2), a -> Map(a -> 1), c -> Map(c -> 3))
7.1.4. foldLeft
传入初始值后,多数组元素叠加
val a = Array(1,2,3,4,5)
a.foldLeft(0)(_+_) //15
7.1.5. reduce
val a = Array(1,2,3,4,5)
a.reduce(_+_) //15
7.1.6. aggregate
aggregate函数将每个分区里面的元素进行聚合,然后用combine函数将每个分区的结果和初始值(zeroValue)进行combine操作。这个函数最终返回的类型不需要和RDD中元素类型一致。
计算两个数组的和
val a = Array(Array(1,2,3),Array(4,2,3))
- aggregate(0)(_+_.sum,_+_)
7.1.7. flatMap
先map后foldLeft
7.1.8. reduceByKey
7.1.9. sortByKey
7.1.10. sortBy
8. 类
8.1. 类的定义和getset方法
带getter和setter属性
var
只带getter属性
val
private和private[this]
8.2. 主构造器和辅助构造器
1、跟在类名后面的是主构造器
2、辅助构造器的名称为this定义,必须执行def
3、辅助构造函数相当于java中的其他的累的构造器,所接受的参数不能多于主类的
例如
class TestScala1 (val name: String,var password:String ) {
def this(name: String) = this(name,null)
}
8.3. object半生对象
用对象作为单例或存放工具方法
可作为伴生对象
用类的伴生对象的apply方法创建新的实例
扩展App特质作为main方法使用
枚举
8.4. 包
包可见性private[spark]
重命名import java.util.{HashMap => JHashMap}
隐式导入:和Java程序一样java.lang总是被默认引入,scala也默认引入
8.5. 模式匹配
Scala有一个非常强大的模式匹配机制,可以应用到很多场合:如switch、类型查询,并可以结合样例类完成高级功能
object TestScala1 { def main(args: Array[String]): Unit = { val aa = new TestScala2 println(aa.test("zhangsan")) } } class TestScala2 { def test(name: String): String = { //和java的switch一样,只是关键字变成了match,分在=》后面的是一个方法体,而=》符号表示匿名函数 name match { case "zhangsan" => TestScala2.test(name) case "lisi" => name+"fdsfas" case _ => name+"fdsfas" } } } object TestScala2 { def test(name: String): String = { "wangwu" } } |
8.6. 样本类
caseclass TestScala1(valname: String, varpassword: String) { defthis(name: String) = this(name, null) defthis() = this(null, null) } |
样本类:添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:
添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Var对象。
样本类参数列表中的所有参数隐式获得了val前缀,因此它被当作字段维护。
编译器为这个类添加了方法toString,hashCode和equals等方法。
9. 继承
重新方法:重新一个非抽象的方法必须使用override修饰符
o.isInstanceOf[Cl] //java中的instanceof
o.asInstacneOf[Cl] //java中的 (Cl) o
classOf[Cl] //java中的Cl.class
10. 高阶函数
def fun(f: Double => Double) = {
f(100)
}
fun((x : Double) => 2 * x)
fun(sqrt _)
11. 柯里化
将原来接受两个参数的函数变成接受一个参数的函数的过程。
例如定义一个函数是这样滴:
def first(x:Int) = (y:Int) => x + y
那么调用的时候应该这样写
val second=first(1)
val result=second(2)
实际上柯里化函数将上面的步骤简化了:
简化成这样定义:
def fun(x: Int)(y: Int) = x * y
调用时你可以这样:
fun(6)(7)
也可以这样:
val fun2 = fun(6)_ // 这次调用返回的是一个方法,传入一个值,但是本身这个函数需要两个值,所以我们用”_”来站位我们不知道的另一个参数
val result = fun2(7) // 42
12. 隐式转换
隐式转换:就是将某各类中没有的方法实现,在另一个增强类中实现,然后用一个固定的方式将某各类转换成这个增强类
- 例如:java的file类中并没有read方法,那么我们想读文件,需要利用scala的source这个类帮我们读文件
- 那么,我们重新定义一个类RichFile,接受的参数是File类型,而利用Source.fromFile(file.getPath()).mkString帮助我们读取文件,但是这个方法位于RichFile中,无法让File类直接使用,所以我们需要将File转换成RichFile
- 那么,我们写一个object伴生对象,将我们的File转换成RichFile,书写如下,注意必须有impilicit关键字声明方法:implicit def file2RichFile(f:File)= new RichFile(f)
- 在我们需要使用File调用read方法时,import之前的半生对象即可import Context._
package org.apache.scala.one import scala.collection.mutable.Map import scala.math._ import scala.io.Source import java.io.File class RichFile(val file:File){ def read = Source.fromFile(file.getPath()).mkString } object Context{ implicit def file2RichFile(f:File)= new RichFile(f) } object ImplicitDemo extends App{ import Context._ println(new File("c:/sss.txt").read) 1.to(10) } |
快学scala的更多相关文章
- 快学Scala习题解答—第一章 基础
1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on th ...
- 《快学Scala》
Robert Peng's Blog - https://mr-dai.github.io/ <快学Scala>Intro与第1章 - https://mr-dai.github.io/S ...
- 快学Scala 第十九课 (trait的abstract override使用)
trait的abstract override使用: 当我看到abstract override介绍的时候也是一脸懵逼,因为快学scala,只介绍了因为TimestampLogger中调用的super ...
- 快学Scala 2
控制结构和函数 1.在Scala中,几乎所有构造出来的语法结构都有值.这个特性是为了使得程序更加精简,也更易读. (1)if表达式有值 (2)块也有值——是它最后一个表达式的值 (3)Scala的fo ...
- [Scala] 快学Scala A3L3
Actor 通过尽可能避免锁和共享状态,actor使得我们能够容易地设计出正确.没有死锁或争用状况的程序. Scala类库提供了一个actor模型的简单实现.AKKA是更高级的actor类库. 19. ...
- [Scala] 快学Scala A2L2
集合 13.1 集合的三大类 所有的集合都扩展Iterable特质.集合的三大集合为Seq, Set, Map Seq是一个有先后次序的值的序列,比如数组或列表.IndexSeq允许我们通过整型下表快 ...
- [Scala] 快学Scala A1L1
基础 1.1 声明值和变量 在Scala中,鼓励使用val; 不需要给出值或变量的类型,这个信息可以从初始化表达式推断出来.在必要的时候,可以指定类型. 在Scala中,仅当同一行代码中存在多条语句时 ...
- 快学Scala第一部分
转载: 1.变量声明 val answer = 8 * 5 + 2; //常量 var counter = 0; //变量 //在必要的时候 ,可以指定类型 val greeting:Strin ...
- 《快学Scala》——数组、映射和元组
数组 定长数组:在Scala中可以用Array,初始化一个定长数组.例如: val nums = new Array[Int](10) //10个整数的数组,所有元素初始化为0 val a = new ...
- 《快学Scala》——控制结构和函数
条件表达式 在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值.例如: if (x > 0) 1 else -1 上述表达式的值是1或-1,具体是哪一个取决于x ...
随机推荐
- Maven(二)之Maven项目构建演练
从上一篇的讲解中我们知道了什么是Maven,然后它的安装配置,到修改本地仓库,这篇我们用一个实际的例子,带领大家走进我们的Maven之旅.让我们一起来体验一下Maven的高度自动化构建项目的过程. 一 ...
- golang kafka
golang kafka – hello world https://github.com/Shopify/sarama https://shopify.github.io/sarama/ con ...
- IT职场经纬 |阿里web前端面试考题,你能答出来几个?
有很多小伙伴们特别关心面试Web前端开发工程师时,面试官都会问哪些问题.今天小卓把收集来的"阿里Web前端开发面试题"整理贴出来分享给大家伙看看,赶紧收藏起来做准备吧~~ 一.CS ...
- WPF 杂谈——入门介绍
对于WPF的技术笔者是又爱又恨.现在WPF的市场并不是很锦气.如果以WPF来吃饭的话,只怕会饿死在街头.同时现在向面WEB开发更是如火冲天.所以如果是新生的话,最好不要以WPF为主.做为选择性来学习一 ...
- 分布式键值存储系统ETCD调研
分布式键值存储系统ETCD调研 简介 etcd是一个开源的分布式键值存储工具--为CoreOS集群提供配置服务.发现服务和协同调度.Etcd运行在集群的每个coreos节点上,可以保证coreos集群 ...
- hdu2767强连通加缩点
https://vjudge.net/contest/156688#problem/B 题目说了一大堆,前面的没有用,就是让你判断要加几条边才能强连通,用到缩点的知识 二重循环,判断邻接表下一个点是不 ...
- Spring Boot快速建立HelloWorld项目
Spring Boot使我们更容易去创建基于Spring的独立和产品级的可以”即时运行“的应用和服务.支持约定大于配置,目的是尽可能快地构建和运行Spring应用. 构建环境 JDK 6+ Maven ...
- 用VsCode编辑TypeScript
文地址:https://code.visualstudio.com/Docs/languages/typescript TypeScript是Javascript的超集,它提供了类.模块.接口来帮助你 ...
- java集合系列—ArrayList
ArrayList是工作以来使用频率最高的集合类.以前上课老师说不知道用什么集合类就用ArrayList,好吧,后面就这样了. public class ArrayList<E> exte ...
- TP5.0 PHPExcel 数据表格导出(原)
今天看的是PHPExcel这个扩展库,Comporse 下载不下来,最后只能自己去github里面手动下载,但有一个问题就是下载下来的PHPExcel没有命名空间,所以框架里面的use根本引入不进去, ...