Learning Scala
Scala概述
1. Scala中变量,基本数据类型
- val 与 var
变量类型推断,编译器自动判断变量的类型
1
2
3
4
5
6
7
8
9//val修饰的变量赋值后不可改变
val name="wangafeng"
val name:String="wangafeng"
//var修饰的变量赋值后可以改变
// name="afengwang" 编译器报错
var name="wangafeng"
var name:String="wangafeng"
name="afengwang"Scala中与Java中的数据类型一致,区别是无 基本类型和包装类型 的区别.
- Scala中的数据类型首字母必须大写
所有基本类型的父类是 AnyVal , 所有类的父类是 Any (类似Java中的Object),AnyVal的父类也是Any.
隐式转换
1
2
3
4
5
6val name="wangafeng"
println("my name is ${name}") //隐式转换 底层调用s方法,idea会在字符串前加s
//懒加载
lazy val name="wangafeng"
println(name)return 返回值:Scala中表达式的返回值就是最后一行代码的执行结果
- lazy 懒加载:在第一次使用时才会去初始化
1.1 Scala中的操作符
与java类似,特殊的地方如下:
- 每个操作符都是一个函数
- 不支持三元运算符
- 不支持 – ++
- 除了:操作符,其他都是从左往右进行连接
1
2
3
4//每个操作符都是一个函数
val a=10
val b=20
val c=a.+(b) //val c=a+b
2. 程序控制流程结构
2.1 条件判断 if - else
1 | if(Boolean_expression){ |
2.2 循环 while ,do while ,for
while
1
2
3while(condition){
conditional code;
}do-while
1
2
3
4do{
}while(condition)for
1
2
3
4
5
6
7
8
9
10
11
12
13
14for( i <- 1 to 10){
println(i)
}
//for循环的守护模式
for(i <- 1 to 10> if i%2==0){
println(i)
}
//打印九九乘法表
for(i <- 1 to 9;j <- 1 to i){
print("...")
}break,continue,Scala中不支持.需要引入 Breaks 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import scala.util.control.Breaks
object App{
def main(args:Array[String]){
var a=0
val numList=1 to 10
val loop=new Breaks
loop.breakable{
for( a <- numList ){
println("Value of a: ${a}")
}
if(a == 4){
loop.break
}
}
println("After the loop")
}
}循环表达式
1
2
3Range是左闭右开区间;[ ) //Range是一个类
until是左闭右开区间;[ ) //until是一个方法
to是左闭右闭区间; [ ] //to是一个方法
- yield关键字,基于一个已有的集合来构建一个新的集合
1
2
3
4
5
6
7val arrays=Array("hadoop","strom","spark")
val arraysUpper= for(array <- arrays) yield{
array.toUpperCase
}
println(arraysUpper.mkString("\t"))
3. 集合(Array List Set Map) 不变(默认)与可变集合
3.1 Tuple元组
元组可以装着多个不同类型的值,下标是从1开始的,最多支持22元组(22中类型元素)
获取元组中的值:a._1 a._2 a._n
1 | val tuple=("Hadoop","Storm","Spark",1,10,100) |
3.2 Array数组
不变数组 Array
1
2
3
4
5
6val arr=new Array[Int](8)
println(arr)
println(arr.toBuffer)
val arr3=Array("hdaoop","storm","spark")
println(arr3(2)) //与java访问数组中元素不同的是,是通过()来访问的.可变数组 ArrayBuffer
1
2
3
4
5
6
7val arrayBuffer=ArrayBuffer[Int]()
arrayBuffer +=1 //尾部追加一个元素
arrayBuffer +=(2,3,4,5) //追加多个元素
arrayBuffer ++=Array(6,7) //追加一个数组
3.3 List集合
不变集合List
1
2
3
4
5
6val list=List(1,2,3,4,5) //双向链表?
list.head
list.tail
val list1=1:Nil //将1添加到Nil集合前面
val list2=2:list1可变集合 ListBuffer
1
2
3
4
5val mutableList=scala.collection.mutable.ListBuffer[Int]()
mutable +=1
mutable +=2
mutable +=(3,4,5)
mutable ++= List(6,7,8,9,10)
3.4 Set集合(无重复元素,无索引)
1 | val set=Set(1,2,3,4,5) |
3.5 Map集合
1 |
|
3.6 集合常用API说明 (map reduce)
- foreach() 遍历每一个元素
1
2
3
4val list=(1 to 20).toList
list.foreach(e=>println(e)) //换行打印每个元素
```
2. map()
list.map(item => item2) //list中每个元素值21
2
3. flatMap() //将集合压扁为多个元素
list.flatMap( item => (0 to item).toList) //返回多个值,最小单位1
4. filter()
list.filter(_ %2==0) //找到所有能被2整除的数1
2
5. reduce() //聚合
list.reduce((a,b)=>a+b ) //a表示是累加的值,b是当前元素的值
1 | 6. fold() //聚合,需要指定第一个初始值 |
list.fold(0).reduce((a,b)=>a+b //210
list.fold(90).reduce((a,b)=>a+b) //3001
7. sorted() //排序
val list=List(10,8,9,6,7,4,5,3,1,2)
list.sorted()1
2
8. sortBy()
list.sortBy(item => item.toString) //按照数字进行排序1,10 2,20 3,31,321
2
9. groupBy() //按照给定的函数对数据进行分组,根据函数返回类型进行分组
list.groupBy(item => item%2==0)
//Map(false -> List(1,3,5,,7,9),true -> List(2,4,6,8,10)1
2
3
4
5
6
7
8
9
10
11
12
#### 4. Scala函数式编程
****
##### 4.1 基本函数
注意:def定义的只是方法 可以通过方法名_ 进行方法向函数的转换
// 定义方法的关键字def 后面的max则是方法名 括号内则是参数
def max(x:Int,y:Int):Int={ //定义一个max的方法
if(x>y)
x
else
y
}
//f:T => R f:函数名称 T参数类型 R返回数据类型
max:Int => Int1
2
3
4
5
6
7
8
9
10
11
12
13
14函数与方法的区别?
<p style="text-indent:2em">
如果一个函数在类或者对象中,那么称之为方法.
</p>
方法与函数的转换?(下划线的转化)
<p style="text-indent:2em"><b>语法规定,将函数赋值给变量时,必须在函数后面加上空格和下划</b><p>
<p style="text-indent:2em">
val a =max _ ; 通过_将函数作为值进行传递
</p>
- 局部函数
<p style="text-indent:2em">出现在函数内部的函数,作用域只能是函数内部</p>
def f():Unit{
g
def g():Unit{
println("内部函数")
}
println("外部函数")
}1
2
3
4
5
6
##### 4.2 匿名函数:没有名称的函数,定义的时候不需def,需要=>定义方法体
Scala中定义匿名函数的语法规则就是:(参数名:参数类型)=>函数体
<p style="text-indent:2em">
val sayHelloFunc=(name:String)=>println("Hello,"+name)//通过将它赋值进行调用
</p>
//一个匿名函数的例子,没有函数名字的函数,可以通过赋值调用该匿名函数
//匿名函数通常是用 => 来定义的
(x:Int,y:Int) => {
if(x>y) x else y
}1
2
3
4
5
##### 4.3 高阶函数(函数参数类型是匿名函数的)
- 可以将某个函数传入其他函数,作为参数.
- 接收 __其他函数作为参数的函数__ ,被称作高阶函数
//定义一个高阶函数
def greeting(name:String,func:String=>Unit)={
func(name)
//方法体里面调用了参数中的方法
}
def main(args:Array[String]):Unit{
def sayHelloFunc(a:String):Unit{
println(“name=${a}”)
}
//调用高阶函数
greeting(sayHelloFunc_)
}
//定义一个高阶函数用于两个数的+-/运算
def opera(x:Int,y:Int,func:(x:Int,y:Int)=>Int){
println(result+”${func(x,y)}”)
}
opera(1,2,(x,y)=>x+y)
opera(1,2,(x,y)=>x-y)
opera(1,2,(x,y)=>xy)
opera(1,2,(x,y)=>x/y)
//可以用符号代表一个数
opera(1,2,+)
opera(1,2,-)
opera(1,2,*)
opera(1,2,/_)
//Scala常用高阶函数
Array(1,2,3,4,5).map(2_)
(1 to 9).map(““).foreach(println)
(1 to 20).filter(%2==0)
(1 to 9).reduceLeft( _) //1234567891
2
3
4
5
#### 5. 面向对象编程
- Java
class 类
属性
方法
静态属性
静态方法
interface 接口
enum 枚举1
2
- Scala(无static关键字)
class 类,和java是一样的,区别是无静态方法和关键字
object 单例,为了解决class没有static修饰的问题
trait 特质,类似与java的接口来使用
>> 可以包含已经实现的方法或者属性
>> 一个类可以继承(实现)多个特质1
2
3
4##### 5.1 Scala中类修饰符,作用域
- public: 默认,公共的
- protected: 受保护的,当前包中可以使用.scala中不推荐使用
- private: 私有的
private[this] > private private class > private[scala]包
1 | ##### 5.2 class中的构造方法 |
class Person(var name:String,age:Int){
//辅助构造函数,方便实例化
def this(){
this(“张三”,8)
}
def this(n:Int){
this()
this.age=n
}
}1
2
6. 对象构建初始化过程
a) 首先初始化父类
b) 然后初始化子类
c) 首先初始化主构造函数
d) 然后初始化辅助构造函数1
2
3
4
5
6
7
8
9
10
11##### 5.3 object伴生对象
<p style="text-indent:2em">如果有一个class,还有一个与class同名的object,那么就称这个object是class的伴生对象,class是object的伴生类.
</p>
<p style="text-indent:2em">
<b>可以互相访问私有的方法和属性</b>
</p>
- apply方法:快速构建实例化
<p style="text-indent:2em"> 定义在object中,表示提供了一种便捷的对象创建的方式,创建对象是apply方法返回的数据类型.
</p>
val array=Array(1,2,4) //调用Array伴生对象的apply方法,快捷的对象创建方式1
2<p style="text-indent:2em"> 定义在class中,方便获取数据的值
</p>
val array=Array(1,2,4)
println(array(1)) //11
2
3
4
5
6
7
8
- update方法
定义在class中,便捷的数据插入,更新方式
##### 5.4 case class 案例类
<p style="text-indent:2em">
class与object的整合,便捷的创建对象
</p>
case class student(name:String,age:Int) //不需要写apply方法
//默认生成伴生对象
//以下代码是默认生成的
object student{
def apply(name:String,age:Int)=new Student(name,age)
}
1 |
|
trait A{
}
trait B{
}
trait C{
}
class D extends A with B with C with D{
}1
2
3
4
5
6
7
8
9
#### 6. 模式匹配(match)
****
<p style="text-indent:2em">
类似与java中的switch ... case;
</p>
1. __match__ 关键字
2. 类型匹配
object MatchCase{
def f(n:Int):Unit={
n match
case 1 => println(1)
case 2 => println(2)
case _ => prinln(n)
}
}
//类型匹配
def f2(throwable:Throwable)={
throwable match{
case e:IllegalArgumentException => println("参数异常")
case e:IOException => println("IO异常")
case _ => println("其他异常")
}
}
}
//类匹配
case class student(name:String,age:Int)
object student{
}
1 |
|
implicit def inToString(n:Int){
n.toString
}
//一个隐式转换的例子
def top(n:Int)(implicit ord:Ordering[T])
result.top(5)(ord=new scala.math.OrderingString,Int{
val t1=x._2.compare(y._2)
if(t1!=0){
t1
}else{
val t2=x._1.compare(y._1)
t2
}
})`