文章目录
- 引言
- 大数据介绍
- 大数据与云计算区别
- 大数据和人工智能的区别
- 大数据和传统的分析(excel)的区别
- scala的特性
- 面向对象特性
- 函数式编程
- 函数式编程的特点:
- 函数式编程的优势
- 静态类型
- 扩展性
- 并发性
- 为什么要学scala
- scala安装
- 简单测试
- 了解Scala
- Scala来源
- Scala解释器
- Scala集成环境配置
- 命名规范
- Scala基本语法
- 换行符
- Scala 包
- 定义包
- 引用
- Scala 数据类型
- Scala 基础字面量
- Scala 转义字符
- Scala变量
- 变量类型声明
- 变量推断
- Scala 多个变量声明
- 其他类型
- var和val的区别
- 可变和不可变?
- Maven项目整合scala
- Scala类型转换
- Scala访问修饰符
- 私有(Private)成员
- 保护(Protected)成员
- 公共(Public)成员
- 作用域保护
引言
推荐学习视频
大数据介绍
主要工作:数据统计分析(hadoop工程师、spark工程师、flink工程师、数仓工程师、BI工程师、ETL工程师 、大数据平台工程师)
大数据与云计算区别
大数据可以做数据分析统计,而云计算可以为大数据提供一套资源利用的平台,因此大数据很多时候基于云计算。
大数据和人工智能的区别
首先人工智能基于大数据,大数据为人工智能提供重要的海量数据
大数据和传统的分析(excel)的区别
采用excel处理数据的方式早已不能承担海量数据的处理
scala的特性
面向对象特性
Scala是一种纯面向对象的语言,每个值都是对象,包括基本数据类型(即布尔值、数字等)在内,当然函数也是对象。
类可以被子类化,对象的数据类型以及行为由类和特质描述。
类抽象机制的扩展有两种途径:一种途径是子类继承,另一种途径是灵活的混入机制。这两种途径能避免多重继承的种种问题。
函数式编程
Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。
更进一步,程序员可以利用Scala的模式匹配,编写类似正则表达式的代码处理XML数据。
纯粹的函数编程语言编写的函数没有变量。因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可有得到不同的输出,因此,这种函数式有副作用的。
函数式编程的特点:
函数是一等公民
以表达式为中心
无副作用
只用纯函数来构造函程序,或者说函数没有副作用。
不修改状态
引用透明
函数式编程的优势
代码简洁,开发速度快
接近自然语言,易理解
易于代码管理
适合并发编程
适用于热升级
静态类型
Scala具备类型系统,通过编译时检查,保证代码的安全性和一致性。类型系统具体支持以下特性:
泛型类
协变和逆变
标注
类型参数的上下限约束
把类别和抽象类型作为对象成员
复合类型
引用自己时显式指定类型
视图
多态方法
扩展性
Scala的设计秉承一项事实,即在实践中,某个领域特定的应用程序开发往往需要特定于该领域的语言扩展。Scala提供了许多独特的语言机制,可以以库的形式轻易无缝添加新的语言结构:
任何方法可用作前缀或后缀操作符。
可以根据预期类型自动构造闭包。
并发性
Scala使用Actor作为其并发模型,Actor是类似线程的实体,通过邮箱发收消息。Actor可以复用线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个。在2.10之后的版本中,使用Akka作为其默认Actor实现。
为什么要学scala
1.优雅
框架的而用户是应用开发程序员,API是否优雅直接影响用户体验
2.速度快
Scala语言表达能力强,一行代码抵得上java多行,开发速度快,scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多
3.能融合到Hadoop生态圈
Hadoop现在是大数据实施标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。
JVM语言大部分可能会想到Java,但java做出来的API太丑,或者想实现一个优雅的API太费劲
scala安装
安装参考
简单测试
var a =10+20
可以看出scala是一种弱类型语言
了解Scala
Scala来源
Scala 是 Scalable Language 的简写,是一门多范式的编程语言
联邦理工学院洛桑(EPFL)的Martin Odersky于2001年基于Funnel的工作开始设计Scala。
Funnel是把函数式编程思想和Petri网相结合的一种编程语言。
Odersky先前的工作是Generic Java和javac(Sun Java编译器)。Java平台的Scala于2003年底/2004年初发布。.NET平台的Scala发布于2004年6月。该语言第二个版本,v2.0,发布于2006年3月。
截至2009年9月,最新版本是版本2.7.6 。Scala 2.8预计的特性包括重写的Scala类库(Scala collections library)、方法的命名参数和默认参数、包对象(package object),以及Continuation。
2009年4月,Twitter宣布他们已经把大部分后端程序从Ruby迁移到Scala,其余部分也打算要迁移。此外, Wattzon已经公开宣称,其整个平台都已经是基于Scala基础设施编写的。
Scala的预期目标是将面向对象、函数式编程和强大的类型系统结合起来,同时让人能写出优雅、简介的代码。
Scala博采众长,Scala采用了Java和C#语法的大部分,而他们大部分借自于C,C++语法。表达式、语句和代码块和Java一样,还有类、包和引用的语法。除语法之外,Scala还采用了java的其他元素,如他的基本类型、类库和它的执行模式。
函数式编程借鉴了SML,OCaml,和F#为代表的ML家族语言很接近,Scala的隐式参数灵感来自Haskell,基于actor的并发库来自EeLang的思想。
Scala解释器
REPL:Read(取值)->Evaluation(求值)->Printf(打印)-> Loop(循环)。
scala解释器被称为REPL,会快速编译scala代码为字节码,然后交给JVM来执行。
1.计算表达式
2.内置变量
3.自动补全:
在scala>命令行内,可以使用Tab键进行自动补全
例如:输入a.to,按tab键,解析器会显示出一下选项,tocharArray,toLowerCase,toString,toUpperCase。
Scala集成环境配置
Scala的开发工具分两种:
Eclispe 和Idea
安装方式:
在线和离线
idea在线方式介绍:
File->Settings->Plugins->输入"Scala"
命名规范
基本原则:驼峰命名,命名有业务含义。
var|val orderName=“name”
Scala基本语法
Scala 基本语法需要注意以下几点:
区分大小写 - Scala是大小写敏感的,这意味着标识Hello 和 hello在Scala中会有不同的含义。
类名 - 对于所有的类名的第一个字母要大写。
如果需要使用几个单词来构成一个类的名称,每个单词的第一个字母要大写。
示例:class MyFirstScalaClass
方法名称 - 所有的方法名称的第一个字母用小写。
如果若干单词被用于构成方法的名称,则每个单词的第一个字母应大写。
示例:def myMethodName()
程序文件名 - 程序文件的名称应该与对象名称完全匹配(新版本不需要了,但建议保留这种习惯)。
保存文件时,应该保存它使用的对象名称(记住Scala是区分大小写),并追加".scala"为文件扩展名。 (如果文件名和对象名称不匹配,程序将无法编译)。
示例: 假设"HelloWorld"是对象的名称。那么该文件应保存为’HelloWorld.scala"
def main(args: Array[String]) - Scala程序从main()方法开始处理,这是每一个Scala程序的强制程序入口部分。
换行符
Scala是面向行的语言,语句可以用分号(;)结束或换行符。Scala 程序里,语句末尾的分号通常是可选的。如果你愿意可以输入一个,但若一行里仅 有一个语句也可不写。另一方面,如果一行里写多个语句那么分号是需要的。例如
val s = "you are a dog!"; println(s)
Scala 包
定义包
Scala 使用 package 关键字定义包,在Scala将代码定义到某个包中有两种方式:
第一种方法和 Java 一样,在文件的头定义包名,这种方法就后续所有代码都放在该包中。 比如:
package com.org.analysis
class HelloWorld
第二种方法有些类似 C#,如:
package com.org.analysis {class HelloWorld
}
第二种方法,可以在一个文件中定义多个包
引用
Scala 使用 import 关键字引用包
import java.awt.Color // 引入Colorimport java.awt._ // 引入包内所有成员def handler(evt: event.ActionEvent) { // java.awt.event.ActionEvent... // 因为引入了java.awt,所以可以省去前面的部分
}
import语句可以出现在任何地方,而不是只能在文件顶部。import的效果从开始延伸到语句块的结束。这可以大幅减少名称冲突的可能性。
如果想要引入包中的几个成员,可以使用selector(选取器):
import java.awt.{Color, Font}// 重命名成员
import java.util.{HashMap => JavaHashMap}// 隐藏成员
import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了
注意:默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,这里也能解释,为什么以scala开头的包,在使用时都是省去scala.的。
Scala 数据类型
分为值类型和引用类型
scala中所有的值都有类型,包括数值和函数。
Unit是值类型,它只有一个实例对象
Nothing是所有类型的子类,它没有一个具体的实例对象,一个产能关键的应用如:抛出异常、程序exit、无限循环等。
Nothing是所有类型的子类,也是NULL的子类,Nothing没有对象,但是可以用来定义类型。例如:如果一个方法抛出异常,则异常的返回值类型就是Nothing(虽然不会返回)
Null是所有引用类型的子类,它只有一个实例对象null,主要用来和其他的JVM语言进行互操作。
Scala 与 Java有着相同的数据类型,下表列出了 Scala 支持的数据类型:
Byte | 8位有符号补码整数。数值区间为 -128 到 127 |
---|---|
Short | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 |
Float | 32 位, IEEE 754 标准的单精度浮点数 |
Double | 64 位 IEEE 754 标准的双精度浮点数 |
Char | 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF |
String | 字符序列 |
Boolean | true或false |
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null 或空引用 |
Nothing | Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。 |
Any | Any是所有其他类的超类 |
AnyRef | AnyRef类是Scala里所有引用类(reference class)的基类 |
提示:
和java不同的是,scala没有基本类型和包装类型之分,这些类型都是类,有自己的属性和方法。
Scala 基础字面量
Scala 非常简单且直观。接下来我们会详细介绍 Scala 字面量。
整型字面量
整型字面量用于 Int 类型,如果表示 Long,可以在数字后面添加 L 或者小写 l 作为后缀。
0777L
浮点型字面量
如果浮点数后面有f或者F后缀时,表示这是一个Float类型,否则就是一个Double类型的。实例如下:
0.0
1e30f
3.14159f
1.0e100
.1
布尔型字面量
布尔型字面量有 true 和 false。
符号字面量
符号字面量被写成: '<标识符> ,这里 <标识符> 可以是任何字母或数字的标识(注意:不能以数字开头)。这种字面量被映射成预定义类scala.Symbol的实例。
如: 符号字面量 'x 是表达式 scala.Symbol(“x”) 的简写,符号字面量定义如下:
package scala
final case class Symbol private (name: String) {override def toString: String = "'" + name
}
字符字面量
在 Scala 字符变量使用单引号 ’ 来定义,如下:
'a'
'\u0041'
'\n'
其中 \ 表示转义字符,其后可以跟 u0041 数字或者 \r\n 等固定的转义字符。
字符串字面量
在 Scala 字符串字面量使用双引号 " 来定义,如下:
"Hello,\nWorld!"
多行字符串的表示方法
多行字符串用三个双引号来表示分隔符,格式为:""" … “”"。
实例如下:
val foo = """锋芒极客
www.baidu.com
www.w3cschool.cc
www.pc.qq.com
以上三个地址都能访问"""
Null 值
空值是 scala.Null 类型。
Scala.Null和scala.Nothing是用统一的方式处理Scala面向对象类型系统的某些"边界情况"的特殊类型。
Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。
Scala 转义字符
下表列出了常见的转义字符:
转义字符 | Unicode | 描述 |
---|---|---|
\b | \u0008 | 退格(BS) ,将当前位置移到前一列 |
\t | \u0009 | 水平制表(HT) (跳到下一个TAB位置) |
\n | \u000a | 换行(LF) ,将当前位置移到下一行开头 |
\f | \u000c | 换页(FF),将当前位置移到下页开头 |
\r | \u000d | 回车(CR) ,将当前位置移到本行开头 |
\ " | \u0022 | 代表一个双引号(")字符 |
\ ’ | \u0027 | 代表一个双引号(")字符 |
\ | \u005c | 代表一个反斜线字符 ’ \ ’ |
0 到 255 间的 Unicode 字符可以用一个八进制转义序列来表示,即反斜线‟\‟后跟 最多三个八进制。
Scala变量
在学习如何声明变量与常量之前,我们先来了解一些变量与常量。
变量: 在程序运行过程中其值可能发生改变的量叫做变量。如:时间,年龄。
常量 在程序运行过程中其值不会发生变化的量叫做常量。如:数值 3,字符’A’。
变量声明
在 Scala 中,使用关键词 “var” 声明变量,使用关键词 “val” 声明常量。
基本语法:
var|val 变量名[:变量类型] =变量值
使用var 或val定义一个变量
使用var(variable)声明变量-可以被重新赋值。
使用val(value)声明常量-引用不可变
val修饰的变量,想当于java中final修饰的变量;
声明变量实例如下:
var myVar : String = "flag"
var myVar : String = "laughter"
以上定义了变量 myVar,我们可以修改它。
声明常量实例如下:
val myVal : String = "Foo"
以上定义了常量 myVal,它是不能修改的。如果程序尝试修改常量 myVal 的值,程序将会在编译时报错。
变量类型声明
变量的类型在变量名之后等号之前声明。定义变量的类型的语法格式如下:
var VariableName : DataType [= Initial Value]或val VariableName : DataType [= Initial Value]
变量推断
在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。
所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。
var number = 10;
val charact = "Hello, Scala!";
以上实例中,number 会被推断为 Int 类型,charact 会被推断为 String 类型。
Scala 多个变量声明
Scala 支持多个变量的声明:
val xmax, ymax = 100 // xmax, ymax都声明为100
如果方法返回值是元组,我们可以使用 val 来声明一个元组:
scala> val pa = (40,"try")
pa: (Int, String) = (40,try)
注意事项:
1.变量名要使用字母或者下划线开始,不要使用数字、特殊符号开始
2.变量名不建议使用关键字
3.变量必须赋值(因为根据值来推断类型)
4.声明变量时,可以不指定变量类型,编译器会根据赋值内容自动推断当前变量的类型。
实例:
package try_demoobject var_demo {def main(args: Array[String]): Unit = {val name:String="try"var password:String="catch";password="it";println(password);//多个变量声明val (a,c,d)=(1,2,"abc")var e,f=100;print(a,c,d);println(e,f);//定义数组val arr=Array(1,2,3,4,5,6,7)println(arr.length)val flag:Boolean=trueval money:Double=6666.66;val salary=99999.99 //推断类型//定义带了类型的方法def add(a:Int,b:Int):Int=a+b;//ifval res:String=if(1>2) "false" else "true"//Unit为空类型,相当于void,使用()进行初始化var u=()println(u)println(flag)println(money)println(add(10,20))}}
其他类型
Any
Any可以接受任意的基本类型和引用类型
var any:Any=null;var anyR:Int=1var anyv:Int=2any=anyRany=anyv
AnyRef
使用AnyRef接收任意的引用类型
var anyR:AnyRef=null
AnyVal
可以使用AnyVal接收任意的基本类型
var anyV:AnyVal=u //unit
anyV=b1 //Boolean
anyV=b //Byte
Null
null值只能被推断为Null类型,null代表空值,可以被赋值给任何AnyRef类型的常量或变量
Nothing
Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。
当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回的类型,这样有一个好处,就是我们可以把返回的值(异常)赋值给其他的函数或变量(兼容性)
Option
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)
val myMap:Map[String,String]=Map("key1"->"value1")val value1:Option[String]=myMap.get("key1")val value2:Option[String]=myMap.get("key2")println(value1) //Some("value1")println(value2) //Noneprintln(value1.get)
var和val的区别
1.内容是和否不变
2.val修饰的变量在编译后,等同于加上final
3.val修饰的变量可以用lazy修饰,而var不能,使用lazy定义变量后,只有在调用该变量时才会实例化这个变量的值。而且惰性变量只能是不可变变量
//lazy修饰val的变量,表示懒加载;var不行
lazy val age=100;
可变和不可变?
可变和不可变,指的的是变量本身存的内容,值类型变量存的是数据本身,变量存的是数据的引用。
Maven项目整合scala
发现不能创建类,需要修改目录的标注:
然后发现只能创.java的类,不能创建.scala类,将scala的sdk绑定到我们的项目:
点击OK
Scala类型转换
自动类型转换
允许低类型的向高类型的转换
val test1:String="67"val b=test1.toIntprintln(b)val c:Int=100;val d:Long=cprintln(d)val ch:Char='0'val ch1:Int=chprintln(ch1)/*定义double*/val test2:Double=1111.111val k:Int=test2.toIntprintln(k)
提示:
1.scala没有像Java一样的强制类型转换
2.自动转时,要求小类型向高类型转换
3.高级类型向低级类型转换的时候需要使用富类型(当前类型中的toInt()等)
Scala访问修饰符
Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。
如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public。
Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。
私有(Private)成员
用 private 关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。
class Outer{class try{private def f(){println("f")}class InnerMost{f() // 正确}}(new try).f() //错误
}
//(new try).f( ) 访问不合法是因为 f 在 try 中被声明为 private,而访问不在类 try 之内。
//但在 InnerMost 里访问 f 就没有问题的,因为这个访问包含在 Inner 类之内。Java中允许这两种访问,因为它允许外部类访问内部类的私有成员。
保护(Protected)成员
在 scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。
package p{
class Super{protected def f() {println("f")}}class Sub extends Super{f()}class Other{(new Super).f() //错误}
}
Sub 类对 f 的访问没有问题,因为 f 在 Super 中被声明为 protected,而 Sub 是 Super 的子类。相反,Other 对 f 的访问不被允许,因为 other 没有继承自 Super。而后者在 java 里同样被认可,因为 Other 与 Sub 在同一包里。
公共(Public)成员
Scala 中,如果没有指定任何的修饰符,则默认为 public。这样的成员在任何地方都可以被访问。
class Outer {class try {def f() { println("f") }class InnerMost {f() // 正确}}(new try).f() // 正确因为 f() 是 public
}
作用域保护
Scala中,访问修饰符可以通过使用限定词强调。格式为:
private[x]
protected[x]
这里的x指代某个所属的包、类或单例对象。如果写成private[x],读作"这个成员除了对[…]中的类或[…]中的包中的类及它们的伴生对像可见外,对其它所有类都是private。
package bobsrockets{package navigation{private[bobsrockets] class Navigator{protected[navigation] def useStarChart(){}class LegOfJourney{private[Navigator] val distance = 100}private[this] var speed = 200}}package launch{import navigation._object Vehicle{private[launch] val guide = new Navigator}}
}
上述例子中,类 Navigator 被标记为 private[bobsrockets] 就是说这个类对包含在 bobsrockets 包里的所有的类和对象可见。
比如说,从 Vehicle 对象里对 Navigator 的访问是被允许的,因为对象 Vehicle 包含在包 launch 中,而 launch 包在 bobsrockets 中,相反,所有在包 bobsrockets 之外的代码都不能访问类 Navigator。