简单总结一下scala这门编程语言,希望能让大家快速入门。
一、scala简介
介绍:
scala是一门多范式,命令行式编程语言,将面向对象和函数式编程结合在一起并且基于JVM之上的语言。
作者:
scala的作者叫马丁·奥德斯基,同时也是Java JVM的开发者兼Java泛型的创始人。所以scala是基于java开发的,scala的任务也是基于JVM(虚拟机)基础之上。
发行时间:
2004年推出第一版scala,然后在2009年推出2.x版本
应用:
底层脚本编写、spark开发等
学习scala的目的:
1)适合大数据开发
2)语法也比较简单:对比Java来说,实现同样的功能,scala的代码量会更少一点,开发敏捷
3)运行速度快:scala语言表达能力强,一行相当于java的多行代码,开发快,是静态编程的语言
4)适合hadoop生态:能融入hadoop生态,可以使用基于spark技术栈,进行Hadoop内的操作,主要还是能无缝对接HDFS
简单回顾一下java,因为scala是基于Java开发的,所以scala同样也可以导入Java的类库使用:
主要由JDK、JRE、JVM三部分组成:
JDK(Java Development Kit):是 Java语言的软件开发工具包(SDK)。在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。
JRE(Java Runtime Environment,Java运行环境):包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)
JVM(Java Virtual Machine虚拟机):JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
二、声明变量的方式
val和var
1)val:只能初始化一次,但是可以调用,类似Java中定义的常量final
2)var:同java的变量定义一样,可随时赋值修改
注意:
在声明变量的时候,尽量使用val,因为声明的变量在被调用或使用(在网络传输过程中),会发生序列化和反序列化操作,那么可能会发生数据值被传错的情况,造成数据丢失。
三、数据类型
Any:类似Java中的Object,是Scala数据类型中的顶级父类。如果不想写死一个类型,可以使用顶级父类Any。
基本数据类型:
1)Byte
2)Char
3)Short
4)Int
5)Long
6)Float
7)Double
8)Boolean
注意:首字母都是大写,每个都相当于Java里的引用类型,但是没有Java里的包装类型
Scala内部提供了一些加强版类型:
1)RichInt
2)RichDouble
3)RichChar等类型
四、自增写法
Java中自增可以用++表示,scala没有这种表达方式,只有:
+=value
如:count+=1
五、scala中的apply函数
apply函数(初始化函数):
这个apply函数其实相当于我们在定义的一些类的时候,有的类需要new,才能创建,但是在scala编程中,为了简化使用者难度,有一些操作,是在内部进行初始化,相当于说,使用者不需要再去new类或者对象,而是直接调用。如:
Java中 new Person()
Scala中 Person()
六、if表达式
java和C++中有一个三目运算符 ?:和if表达式表示同样的意思
而scala的if/else是将java、C++的if/else语法结构和三目运算符结合在一起了
如:x > 0 ? 1 : -1 等价于scala中的 if (x>0) 1 else 0
七、块表达式和语句终结符 ;
1)在scala语言中不需要语句终结符,默认一行一条语句。
对比:java中需要用;(分号)表示语句的终结。
2)块表达式:指的是{}中的值,只要被当前这个{}包含的叫块表达式
八、循环
1)增强型for循环
java例子:
int[] array = {1,2,3,4,5,6};
for (int i : array) {
if (i!=null){
System.out.print(i);
}
}//输出结果为:123456
scala例子:
val array = Array(1,2,3,4,5,6)
for (i <- array){
print(i)
}//输出结果为:123456
总结:scala中用 <-(左箭头) 代替了 :(冒号)
2)生成器表达式(scala中之所以叫这个名字是因为该表达式会基于集合生成单独的数值,左箭头<- 操作符用于像列表这样的集合进行遍历)
对于数值的递增递减问题
java例子:
递增:for (int i = 0, i < 10, i++){}
递减:for (int i = 10, i > 0, i--){}
scala例子:
递增:for (i <- 1 to 10){}
递减:for (i <- (1 to 10).reverse){}
总结:对于循环来说,scala中不同于java在于scala提供了Range类型取代了java中的数值操作
补充:
Range类型
1. 1 to 10 //表示Int类型的Range,包括区间上限,步长为1(从1到10)
2. 1 until 10 //表示Int类型的Range,不包括区间上限,步长为1(从1到9)
3. 1 to 10 by 3 //表示Int类型的Range,不包括区间上限,步长为3(1、4、7、10)
4. 10 to 1 by -3 //表示Int类型的递减Range,包括区间下限,步长为-3(10、7、4、1)
5. 1f to 10.3f by 3.1f// Float类型的Range,步长可以不等于1(1.0、4.1、7.2、10.299999)
3)foreach遍历
注意:foreach没有返回值,所以大多时候都不会使用foreach
例子:val array = Array(1,2,3,4,5,6)
array.foreach(x => print(x))
//输出结果为:123456
4)循环控制
A)if守卫
例子:for (i <- 0 to 10 if i!=0 if i%2==0) { print(i) }
//输出结果为:2 4 6 8 10
B)filter(过滤)等方式实现循环控制
例子:val array = Seq("a","b","c","d","e")
array.filter(_.startsWith("a")).foreach(println)
//输出结果为:a
//表示过滤出数组里每个元素首字母为“a”的元素,然后遍历打印
九、scala中函数和方法的定义
1)函数基本语法
val func1 =(参数:类型) => (函数体) //函数分匿名函数和非匿名函数,函数可以作为参数传递
例子:val func1 = (x:Int) => x*2
print(func(2))
//输出结果为:4
2)方法基本语法
方法关键字def 方法名(方法参数:参数类型): 方法返回值类型=方法体
例子:斐波那契数列(递归)方法实现
def fibonacci(n:Int):Int = {
if(n<=2) 1 else fibonacci(n-1)+fibonacci(n-2)
}
3)scala中可以为函数的参数指定默认值
设置了默认值,调用函数的时候,如果没有传参则会使用默认值;如果传参了,就会取代默认值
十、scala中的高阶函数
1)作为参数的函数
函数格式:val 变量名 = (参数:参数类型) => 函数体
例子:val arr = Array(1,2,3,4,5,6)
val func1 = (x:Int) => x*2
arr.map(func1) //将函数作为参数传入map方法中
//输出结果为:2 4 6 8 10
2)匿名函数
在scala中你可以不需要给一个函数命名,没有将函数赋给变量的函数可以称为匿名函数
例子1:
arr.map((x:Int) => x*2) //结果同上
例子2:
arr.map(_*2) //结果同上
3)柯里化
概念:指的是把原来一个参数位接受多个参数的函数变换成一个参数位只接受一个参数的函数的过程
非柯里化例子:def add(x:Int,y:Int) =x+y
print(add(1,2))
//输出结果为:3
柯里化例子: def add(x:int)(y:Int) =x+y
print(add(1)(2))
//输出结果为:3
柯里化风格的特点:
简化主函数的复杂度,提高主函数的自闭性。提高功能上的可扩张性、灵活性。可以编写出更加抽象,功能化和高效的函数式代码。
4)闭包
概念:闭包是一个函数,指函数的返回值依赖于声明在函数外部的一个变量或多个变量。
即:可以访问不在当前作用域范围内的一个函数
例子:val y = 10
val add =(x:Int) =>{x+y}
print(add(5))
//输出结果为:15
//其中x为形参,y为自由变量,且y不在add函数作用域范围内
十一、scala中方法使用(举例部分)
1)flatMap
含义:返回迭代器中的元素
例子: val flatmap =List("apple1 apple2","apple3 apple4")
flatmap.flatMap(_.split(" ")).foreach(x =>print(x+" "))
//结果返回一个对象apple1 apple2 apple3 apple4
扩展:flatMap和map有什么区别?
先举个map的例子:
val flatmap =List("apple1 apple2","apple3 apple4")
flatmap.map(_.split(" ")).foreach(x =>print(x+" "))
//结果返回两个对象
//对象一 apple1 apple2
//对象二 apple3 apple4
总结:我们可以看出
map:会对每一条数据进行指定的操作,然后为每一条数据返回一个对象
flatMap:相当于集合了map+flatten两步操作,在map的基础上还会对每条数据map操作后的结果进行扁平化,类似迭代每个元素然后最终合并成一个对象返回
2)Zip族方法
含义:将传进来的两个参数中相应位置上的元素组成一个pair数组。如果其中一个参数元素比较长,那么多余的参数会被删掉
例子:val z1=List("C", "C++", "Java", "Scala")
val z2=List(100, 90, 75, 83)
z1.zip(z2).foreach(x =>print(x+" "))
//结果为 (C,100) (C++,90) (Java,75) (Scala,83)
3)lazy关键字
含义:在Scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算,这种特性针对于特别耗时的计算操作比较生效,比如打开文件进行IO,进行网络IO等。
例子:import scala.io.Source._
lazy val lines = fromFile(本地文件路径).mkString
4)SortedMap
含义:返回元素按照key的字典排序的映射
例子1:val gredes = SortedMap(("D",90),("E",86),(C",88),("B",78),("A",93))
grades.foreach(x =>print(x+" "))
//输出结果为:("A",93)("B",78)("C",88)("D",90)("E",86)
例子2:val gredes = SortedMap(("1",90),("3",86),(2",88),("5",78),("4",93))
grades.foreach(x =>print(x+" "))
//输出结果为:("1",90)("2",88)("3",86)("4",93)("5",78)
5)LinkedHashMap
含义:安插入时的顺序返回元素
例子:var status=mutable.LinkedHashMap((5,"apple"))
status +=((3,"orange"))
status +=((6,"banana"))
println(status)
//结果:Map(5 -> apple, 3 -> orange, 6 -> banana)
6)ListMap
含义:按插入的相反顺序返回元素
例子:var status=mutable.ListMap((1,"a"))
status +=((2,"b")) //结果:Map(2 -> b, 1 -> a)
status +=((3,"c")) //结果:Map(3 -> c, 1 -> a, 2 -> b)
7)scala版的wordcount入门案例
//第一步,导入scala相关IO包
import scala.io.Source._
//第二步,导入本地文件,并转成字符串类型
val lines:String = fromFile("E://test.txt").mkString
//第三步,将字符串转成集合类型按规则拆分成单个字符串
val words:List[String] = lines.toList.flatMap(_.split(" "))
//第四步,对words进行map聚合标记,返回一个tuple元组
val tuples:List[String,Int] = words.map((_,1))
//第五步, 按key分组
val group:Map[String,List[String,Int]] = tuples.groupBy(_._1)
//第六步,统计每个key对应value值的长度,即词频
val sum:Map[String,Int] = group.mapValues(_.size)
println(sum)
//结果
//Map(suke -> 1, Tom -> 1, Jerry -> 1, beta -> 1, hello -> 4)
未完待续,请关注scala入门篇(二)