Scala语言特点
优雅
快
object 相当于一个静态的对象
def 方法
unit 相当于void
一、数据类型
Byte Short Long
Float Double Char
String Boolean
Unit(=void)
Null
Any
Nothing
AnyRef
符号字面量:
写法:<标识符> `x
<标识符>可以是任何字母或数字的标识(不能以数字开头)
这种字面量被映射成预定义类scala.Symbol的实例。
二、变量:
1、变量声明
var 变量名:变量类型 = 变量值
变量声明一定需要初始值,否则会报错。
三、方法定义
格式:def methodName(参数名:参数类型):返回值 = 方法体
不指定返回值根据方法体自行推倒:
def methodName(参数名:参数类型) = {方法体}
无返回值:
def methodName(参数名:参数类型) = {没有返回值方法体}
不传递参数
def methodName() = {方法体}
若无参数传递可以不加()
val f3:(Int,Int) => Int={(x,y) => x*y}
filter 拦截
四、方法和函数的区别
1、在java中函数和方法是没有区别的
2、在scala中
-函数可以作为参数传入到方法中运行
-函数可以调用方法
|-方法转换为函数
|-val f1= m _ (m是一个方法可以通过_转换成函数)
五、wordCount实现
1、切分
2、压平
var arr2=arr.flatMap(x=>x.split(" "))
arr2: Array[String] = Array(Hadoop, Hive, Sqoop,
Hive, Hbase, Hive, Hadoop, Spark)
3、计数//可省略
4、合并汇总(groupby)
var arr3=arr2.groupBy(x=>x)
arr3: scala.collection.immutable.Map[String,Array[String]]
= Map(Sqoop -> Array(Sqoop),
Hbase -> Array(Hbase),
Hive -> Array(Hive, Hive, Hive)
, Spark -> Array(Spark),
Hadoop -> Array(Hadoop, Hadoop))
scala> var arr4=arr3.map(x=>(x._1,x._2.length))
arr4: scala.collection.immutable.Map[String,Int] = Map(Sqoop -> 1, Hbase -> 1, Hive -> 3, Spark -> 1, Hadoop -> 2)
TopN:
object ScalaWordCount {
def main(args: Array[String]): Unit = {
//造数据
var list=List(" I Love cw ","cw hava a big JB","cw is very filthy")
//数据转换采用链式编程
var ans=list.flatMap(line=>line.trim()
.split(" ")
.filterNot(word=>word.isEmpty))
.groupBy(x=>x)
.map(x=>(x._1,x._2.length))
.toList.sortBy(x=> - x._2)
.take(3)
print(ans.toString())
//对每一行数据进行切割
//转换,去掉单词空格
//数据过滤 .filterNot(word=>word.isEmpty)
//将单词转换为二元数组
}
}
—————————————————————–+
函数式编程
使用java实现函数式编程
接口==规则==函数
jdk1.8 Lambda表达式实现函数式编程
->
数组
set
map
list
可变可不变
+=
++=
-=
remove
当var创建
伴生对象
Object
跟类名相同
且在同一个文件中
可以访问private的属性和方法
private 当前类和伴生对象
private[this] 只在当前类中可以使用
指定包访问权限
private[package] classname
构造器(构造方法)
-主构造器 :class className(val/var propertyName:propertyTpe,…)
[
-辅助构造器 :this(){}
跟类名交织在一起的叫主构造器,主构造器中的属性会成为这个类的成员变量
辅助构造器是对主构造器的扩展
辅助构造器第一行一定要先调用主构造器
辅助构造器的变量不用val var定义
def this(id:Long){}
没有加var/val不会成为成员变量只能在内部使用
class eople paivate(参数)//私有的构造器只能在伴生对象中使用
对象和实例是两回事
对象 object
静态对象 单例对象
实例 new
apply方法:
object名字后面跟括号,括号中有参数,执行时会寻找参数个数一样的apply方法
7、 Scala函数的求值策略
Scala中,有两种函数参数的求值策略
Call By Value:对函数实参求值,且仅求一次
Call By Name:函数实参每次在函数体内被用到时都会求值
继承实现特质
-重写非抽象方法必须加overwrite
-trait(类似java中的接口) (特质) 可以定义有实现的方法
-在scala中,第一个继承和实现都使用extend
-动态实现特质
在Object中new出来后with 特质
=*=多态:
必须重写
接口指向实现类
父类引用指向子类
模式匹配(switch)
一旦一个匹配上了就不会继续往下匹配了
匹配字符串内容、数组、List、元组、数据类型、对象
det contentMatch(str:string)=str match{
case “value” => println(“”)
case “value” => println(“”)
case _=>
}
特殊数组
0::Nil 只有0元素是的List
7::9::Nil 只有7,9元素的ist
x::y::z 只有三个元素的List
m::n 拥有head和tail的数组
闭包(函数的嵌套):
在一个函数定义中,包含另外一个函数的定义;
并且在内函数中可以访问外函数中的变量。
def mulBy(factor:Double)=(x:Double)=>x*factor
var triple = mulBy(3)
triple: Double => Double =
val half = mulBy(0.5)
half: Double => Double =
println(triple(10)+” “+half(8))
30.0 4.0
柯里化:
def add(x:Int,y:Int) =x+y
def add(x:Int)(y:Int) =x+y
包:
scala中的包和java中的包一样
scala中的包可以嵌套
import可以写在任何地方
包对象:
-包可以包含类、对象和特质,但不能包含函数或者变量的定义。很不幸,这是Java虚拟机的局限。
-把工具函数或者常量添加到包而不是某个Utils对象,这是更加合理的做法。Scala中,包对象的出现正是为了解决这个局限。
-Scala中的包对象:常量,变量,方法,类,对象,trait(特质)
Scala中文件的访问
val source=scala.io.Source.fromFile(“filePath”)
读取行:
sourec.getLnes()
读取字符:
for(c<-source)
指定字符集
val source=scala.io.Source.fromURL(“filePath”,”Utf-8”)
Scala不支持二进制读取
但是可以通过调用java的InputStream来进行读取
写入文本文件
PrintWriter()
调用的是java的Api
Scala中的集合
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
可变集合和不可变集合
-序列
Vector和Range
Vector是ArrayBuffer的不可变版本,是一个带下标的序列
Range表示一个整数序列
Scala的case class就是在普通的类定义前加case这个关键字,
然后你可以对这些类来模式匹配
scala语言的高级特性
1、泛型类
使用[]来定义泛型参数
什么是泛型函数
函数和方法也可以带类型参数。和泛型类一样,我们需要把类型参数放在
方法名之后
3、 Upper Bounds 与 Lower Bounds
S <: T
这是类型上界的定义。也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类。
U >: T
这是类型下界的定义。也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。
视图鉴定:<%
它比<:适用范围更广,允许所有的子类型,还允许隐
试转换过去的类型。
使用试图鉴定,取代泛型上界
Scala没有定义的转换
使用时需要创建转换规则
协变和逆变:
scala的协变:泛型变量的值可以是本身类型或者其子类的类型
Scala的类或特质的泛型定义中,如果在类型参数前面加入+
符号,就可以使类或特质变为协变。
逆变:
在类或特征的定义中,在类型参数之前加上一个-符号,
就可定义逆变范型类和特征了。
Scala的逆变:泛型变量的值可以是本身类型或者其父类的类型
隐式转换函数
隐式转换函数指的是以implicit关键字申明的带有单个参数的函数
使用implicit申明的函数参数叫做隐式参数。我们也可以使用隐式参数实现隐式的转换
8、 隐式类
所谓隐式类: 就是对类增加implicit 限定的类
,其作用主要是对类的功能加强!
/**
* scala的隐式转换
*/
object ImplicitClass {
implicit class Cala(x:Int){
def add(a:Int): Int =
{
a+x
}
}
def main(args: Array[String]): Unit = {
println(1.add(2))
}
}
隐式类执行的过程:
1、当1.add(2),scala的编译器不会立即报错;在当前域中查找,又没有implicit修饰的,
同时可以将Int作为参数的构造器,并且具有add方法的类,最终找到Calc
2、利用隐式类执行add方法