前言
:Scala即是面向对象的语言,也是面向函数的语言。
Scala简介
Scala是面向对象和面向函数的语言。
Scala可以为你在做大量代码重用和扩展时提供优雅的层次结构,
并可以通过高阶函数来实现这样的目标。
解释:高阶函数是函数式编程里的特性之一,允许函数作为参数传递,
也允许函数作为返回值来返回。
Scala与Java相对比
Scala相较于Java而言,则是相信程序员的优化能力。
Scala语言的特点
1.他是一门现代编程语言。
2.他是一门面向对象(OOP)语言,
每个变量都是一个对象,每个"操作符"都是方法。
(scala语言在面向对象的方面,
要比java更彻底,它同时也是一门函数式编程
(FP)语言,可以将函数作为参数传递。
可以用OOP,FP或者两者结合的方式编写代码)
3.Scala代码通过scala编译成 **.class文件**,然后在JVM上运行,
可以无缝使用已有的丰富的Java类库。即Scala的代码会编译成字节码,
运行在Java虚拟机(JVM)上。
4.针对同一任务,可以有很多种不同的实现方式,
并且可读性以及性能都有不一样的体现。
5.Scala每一次重构,代码的性能或者是可读性都会有极高的提升。
6.Scala提供了一整套工具,让程序员自由选择,无论是mutable数据结构,
immutable数据结构, 并行(parallel)数据结构。
然后在这些选择中,以针对变化万千的任务需求,
这点是Scala做得极好的地方。
7.Scala不是一门纯的函数式编程语言,
所以有别纯函数式语言的区别之一是:
mScala提供变量和常量,而纯函数式编程语言是没有变量这概念的。
Scala语言的应用
kafka - scala - 分布式消息队列,内部代码经常用来处理并发的问题,
用scala可以大大简化其代码
spark - scala - 处理多线程场景方便,另外spark主要用作内存计算,
经常用来实现复杂的算法。
Scala的数据类型
1.Byte
2.Short
3.Int
4.Long
5.Char
6.String
7.Float
8.Double
9.Boolean
注意:其中string处于java.lang包,其他的则处于scala包
Scala的操作符
Scala中操作符即方法,方法即操作符。
Scala中的操作符其实是普通方法调用的另一种表现形式。
算数运算
+-*/
关系运算
<> >= <=
逻辑运算
&& || !
位运算
>> >>> << ~& | ^
比较运算
== !=
符号越考上优先级越高
*/ %
+-
:
=!
<>
&
^
|
前缀操作符
使用时需要空格
+ 加几
- 减几
! 取反
~ 二进制取反
占位符
占位符指的是scala中的下划线_,可以把它当作一个或多个参数使用。
使用占位符的前提要求:每个参数在函数仅出现一次。
使用下划线时,如果类型可以自动推断出,则不用声明类型。
如果无法自动推断类型,则在下划线后自己来显示声明类型即可
Scala语法
变量
//var 用来声明一个变量,变量声明后,在程序执行过程中可以被修改。
package com.biem.test
object test01 {
//声明变量,变量赋值后是可以更改的
var v1 = "hello,scala" //> v1 : String = hello,scala
var v2 = 1314 //> v2 : Int = 1314
v2 = 520
println(v2) //> 520
}
常量
// val 用来声明一个常量,一旦被赋值就不能在进行修改。
package com.biem.test
object test02 {
//声明常量,常量声明后,不允许更改
val v1 = 10.5; //> v1 : Double = 10.5
val v4:Int=100 //> v4 : Int = 100
val v5:String="hello" //> v5 : String = hello
}
判断语句
package com.biem.test
object test05 {
//定义一个常量
val v1 = 6 //> v1 : Int = 6
if(v1>6){
println("big")
}else{
println("small")
} //> small
//化简规则1:
if(v1>6)println("big")else println("small") //> small
val result = if(v1>6){
println("big")
150
"hello"
}else{
println("small")
100
"world"
} //> small
//| result : String = world
}
while for 语句
package com.biem.test
object test06 {
//定义一个数组
val v1 = Array(1,2,3,4,5) //> v1 : Array[Int] = Array(1, 2, 3, 4, 5)
//定义一个变量
var index = 0 //> index : Int = 0
//while语句
while(index < v1.size){
//--通过下标取值的时候用的是(),而不是java中的[]
//--scala是用过()来操作下标的
println(v1(index))
index+=1
} //> 1
//| 2
//| 3
//| 4
//| 5
//for语句
for(x<-v1){
println(x) //> 1
//| 2
//| 3
//| 4
//| 5
}
for(i<-1.to(9)){
println(i) //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
//| 7
//| 8
//| 9
}
1 to 5 //> res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
for(i<-1 to 5){
println(i) //> 1
//| 2
//| 3
//| 4
//| 5
}
}
String类型
//字符串操作 事实上Scala的String类就是java的string类,
//所以可以直接调用java里string的所有方法
//(由于Scala提供了隐式转换的魔法-->
//String类也拥有StringOps类中所有方法的访问权限, 所以可以用这些方法做许多事情)
package com.biem.test
object test03 {
//Scala String类型的操作方法
//定义一个常量
val v1 = "hello,word" //> v1 : String = hello,word
//1.split()方法
val v2 = v1.split(",")
//> v2 : Array[String] = Array(hello, word)
//--repeat方法
val v3 = v1*2 //> v3 : Strin=hello,wordhello,word
//--根据指定的匿名函数做计数统计
v1.count { x =>x=='o' } //> res0: Int = 2
//--去重
v1.distinct //> res1: String = helo,wrd
//--去除头部n个元素,并返回剩余的元素
v1.drop(2) //> res2: String = llo,word
//--去除尾部n个元素,并返回剩余的元素
v1.dropRight(2) //> res3: String = hello,wo
//--判断以xx结尾
v1.endsWith("ld") //> res4: Boolean = false
//--判断某个元素是否存在
v1.exists{x=> x=='z'} //> res5: Boolean = false
//--实现过滤
v1.filter(x=> x!='o') //> res6: String = hell,wrd
//--遍历
v1.foreach{x =>println(x)} //> h
//| e
//| l
//| l
//| o
//| ,
//| w
//| o
//| r
//| d
//--获取头部元素
v1.head //> res7: Char = h
//--从指定的下标开始查找,返回这个元素第一次出现的位置
v1.indexOf('o',5) //> res8: Int = 7
//--获取尾部元素
v1.last //> res9: Char = d
//--反转
v1.reverse //> res10: String = drow,olleh
//--取出前n个元素
v1.take(3) //> res11: String = hel
//--去除末尾几个数
v1.takeRight(3) //> res12: String = ord
//--类型转换
val v4 = "100" //> v4 : String = 100
val v5 = v4.toInt //> v5 : Int = 100
val v6 = v4.toDouble //> v6 : Double = 100.0
}
数字方法区
package com.biem.test
object test04 {
//数字相关的方法
//定义一个数字
val v1 = 1
//--生成指定的区间(range),一般出现在for循环中
v1.to(5) //> res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
//--生成区间,并指定步长
v1.to(5,2) //> res1: scala.collection.immutable.Range.Inclusive = Range(1, 3, 5)
//--指定区间,但不包括终止元素
v1.until(5) //> res2: scala.collection.immutable.Range = Range(1, 2, 3, 4)
//--指定步长(也不包括终止元素)
v1.until(5,2) //> res3: scala.collection.immutable.Range = Range(1, 3)
//--以方法调用的顺序来计算
val v2 = 1.+(2).*(3) //> v2 : Int = 9
//--以操作符的优先级来计算
val v3 = 1+2*3 //> v3 : Int = 7
//--scala的前缀操作符(使用时前面必须加上空格)
//--表示正数
val v4 = +2 //> v4 : Int = 2
//--表示负数
val v5 = -2 //> v5 : Int = -2
//--布尔取反
val v6 = !true //> v6 : Boolean = false
//--二进制取反
val v7 = ~0xab //> v7 : Int = -172
//--为了避免前缀操作符引起的歧义
val v8 = 2.unary_+ //> v8 : Int = 2
val v9 = 2.unary_- //> v9 : Int = -2
val v10 = 2.unary_~ //> v10 : Int = -3
val v11 = true.unary_! //> v11 : Boolean = false
//--类型转换
val v12 = 100 //> v12 : Int = 100
v12.toString() //> res4: String = 100
v12.toDouble //> res5: Double = 100.0
val v13=BigInt(2) //> v13 : scala.math.BigInt = 2
//--实现幂运算
v13.pow(10) //> res6: scala.math.BigInt = 1024
}
Scala Collection
import scala.collection.mutable.ArrayBuffer
/**
知识点:scala的集合(collection)是一个大的概念
包含:Array,List,Set,Map,Tuple
Array:声明,调用及一些主要的方法
mutable:可变
immutable:不可变
**/
object test15 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--声明一个定长的数组,而且直接给他赋值
//--定长就是声明之后长度不可变
val a1=Array(1,2,3,4,5) //> a1 : Array[Int] = Array(1, 2, 3, 4, 5)
//--声明一个变长的数组并赋值
//--变长就是长度可变,比如说追加元素等操作
val a2=scala.collection.mutable.ArrayBuffer(1,2,3,4,5)
//> a2 : scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)
//|
val a3=ArrayBuffer(1,2,3,4,5) //> a3 : scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)
//|
//--声明定长数据,并指定长度
val a4=new Array[Int](4) //> a4 : Array[Int] = Array(0, 0, 0, 0)
//--scala的数组是通过下标取值,下标也是从0开始,与java相同
//--只不过用的是()
a1(1) //> res0: Int = 2
//--赋值
for(i<- 0 to a1.length-1){
println(a1(i)) //> 1
//| 2
//| 3
//| 4
//| 5
}
for(i<- 0 until a1.length){
println(a1(i)) //> 1
//| 2
//| 3
//| 4
//| 5
}
//--用for循环给a4数组赋值,0,1,2,3
for(i<-0 until a4.length){
a4(i)=i
}
a4 //> res1: Array[Int] = Array(0, 1, 2, 3)
//--可变数组的拼接
for(i<-1 to 10){
a3.append(i)
}
a3 //> res2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5,
//| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//--concat:将多个数组的结果合在一起
//--Array.concat只能合并定长的数组
val a5=Array(1,2,3) //> a5 : Array[Int] = Array(1, 2, 3)
val a6=Array(4,5,6) //> a6 : Array[Int] = Array(4, 5, 6)
val a7=Array.concat(a5,a6,a1) //> a7 : Array[Int] = Array(1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5)
//--ArrayBuffer.concat既能合并定长又能合并变长的数组
val a8=ArrayBuffer.concat(a5,a2,a3) //> a8 : scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 1, 2
//| , 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//--生成区间数组,一般会用于生成测试数据集合
val a9=Array.range(5,10,2) //> a9 : Array[Int] = Array(5, 7, 9)
//--生成一个指定的数组,并将匿名函数应用到初始值
//--用途:可以生成有一定函数关系的数列
val a10=Array.iterate(3,7)(x=>x*2) //> a10 : Array[Int] = Array(3, 6, 12, 24, 48, 96, 192)
//--生成指定长度的数组,并将匿名函数应用到数组的下标,默认从0开始
//化简:val a11=Array.tabulate(5)(_*3)
val a11=Array.tabulate(5)(x=>x*3) //> a11 : Array[Int] = Array(0, 3, 6, 9, 12)
//--求和、最值
val a12=Array(1,2,3,4) //> a12 : Array[Int] = Array(1, 2, 3, 4)
//--求数组当中所有元素的和
val sum=a12.sum //> sum : Int = 10
//--求数组中最大值
val max=a12.max //> max : Int = 4
//--求数组中最小值
val min=a12.min //> min : Int = 1
val a13=Array(2,1,5,3,9) //> a13 : Array[Int] = Array(2, 1, 5, 3, 9)
//--通过scala提供的快速排序工具类来实现升序排序
scala.util.Sorting.quickSort(a13)
a13.reverse //> res3: Array[Int] = Array(9, 5, 3, 2, 1)
//--取前n个元素,并返回一个新的数组
val a14=a12.take(2) //> a14 : Array[Int] = Array(1, 2)
//--取尾部n个元素,并返回一个新的数组
val a15=a12.takeRight(2) //> a15 : Array[Int] = Array(3, 4)
//--去除头n个元素,并将剩余的元素返回一个新的数组
val a16=a12.drop(2) //> a16 : Array[Int] = Array(3, 4)
//--去除尾n个元素,并将剩余的元素返回一个新的数组
val a17=a12.dropRight(2) //> a17 : Array[Int] = Array(1, 2)
//--head:把数组的头元素返回
a12.head //> res4: Int = 1
a12.take(1) //> res5: Array[Int] = Array(1)
//--last:把数组的尾元素返回
a12.last //> res6: Int = 4
//--filter
val a18=a12.filter { x => x%2==0 } //> a18 : Array[Int] = Array(2, 4)
val a19=Array("tom,m,23","rose,f,30","mary,m,35")
//> a19 : Array[String] = Array(tom,m,23, rose,f,30, mary,m,35)
a19.map { x => x.split(",") } //> res7: Array[Array[String]] = Array(Array(tom, m, 23), Array(rose, f, 30), A
//| rray(mary, m, 35))
//--过滤出这个数组中的男性数据
val a20=a19.filter { x => x.split(",")(1).equals("m") }
//> a20 : Array[String] = Array(tom,m,23, mary,m,35)
//--过滤出a19当中年龄>25岁的数据
val a21=a19.filter { x => x.split(",")(2).toInt>25 }
//> a21 : Array[String] = Array(rose,f,30, mary,m,35)
val a22=Array(1,2,3,4,5) //> a22 : Array[Int] = Array(1, 2, 3, 4, 5)
//--map:映射方法 作用:将数组中每个元素根据匿名函数,映射到另一个形式
//--特点:数据形式发生变化。但是元素个数没有变
val a23=a22.map { x => x*2 } //> a23 : Array[Int] = Array(2, 4, 6, 8, 10)
val a24=Array("20","30","25") //> a24 : Array[String] = Array(20, 30, 25)
//--操作这个a24,将这个数据类型String->Int
val a25=a24.map { x => x.toInt } //> a25 : Array[Int] = Array(20, 30, 25)
//--操作a19,生成一个新的数组,数组中保存的是每个元素的姓名
val a26=a19.map { x => x.split(",")(0) } //> a26 : Array[String] = Array(tom, rose, mary)
val a27=Array(1,2,3,4) //> a27 : Array[Int] = Array(1, 2, 3, 4)
val s1=a27.mkString //> s1 : String = 1234
val s2=a27.mkString(",") //> s2 : String = 1,2,3,4
val a28=Array("tom,m,23","rose,m,30","mary,m,35")
//> a28 : Array[String] = Array(tom,m,23, rose,m,30, mary,m,35)
//--对a28进行操作,让其中里面元素的年龄都+1
//val a29=a28.map { x => x.split(",")(2).toInt+1 }
a28.map{(x:String)=>
val arr=x.split(",")
val age=arr(2).toInt+1
arr(2)=age.toString
arr.mkString(",")
} //> res8: Array[String] = Array(tom,m,24, rose,m,31, mary,m,36)
//--扁平化map方法
//--特点:映射方法,会改变元素的个数
val a29=Array("hello,world","hello,beijing","hello,chian")
//> a29 : Array[String] = Array(hello,world, hello,beijing, hello,chian)
val a30=a29.flatMap { x => x.split(",") } //> a30 : Array[String] = Array(hello, world, hello, beijing, hello, chian)
val a31=a29.map { x => x.split(",") } //> a31 : Array[Array[String]] = Array(Array(hello, world), Array(hello, beiji
//| ng), Array(hello, chian))
}
List集合
import scala.collection.mutable.ListBuffer
object test16 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--声明一个定长的List
val l1=List(1,2,3,4,5) //> l1 : List[Int] = List(1, 2, 3, 4, 5)
//--声明一个变长的List
val l2 = scala.collection.mutable.ListBuffer(1,2,3,4,5);
//> l2 : scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5)
val l3 = ListBuffer(1,2,3,4,5) //> l3 : scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5)
//--声明一个定长的List
val l4 = 1::2::3::4::5::Nil //> l4 : List[Int] = List(1, 2, 3, 4, 5)
//--声明一个空的List
val l5 = Nil //> l5 : scala.collection.immutable.Nil.type = List()
val l6 = List[Nothing]() //> l6 : List[Nothing] = List()
//--List也是通过下标取值或者赋值,同Array
l1(1) //> res0: Int = 2
//--+:或:+是基于一个定长的List添加元素,并返回一个新的List
0+:l1 //> res1: List[Int] = List(0, 1, 2, 3, 4, 5)
l1:+6 //> res2: List[Int] = List(1, 2, 3, 4, 5, 6)
l1.head //> res3: Int = 1
l1.take(1) //> res4: List[Int] = List(1)
l1.takeRight(1) //> res5: List[Int] = List(5)
l1.last //> res6: Int = 5
l1.drop(2) //> res7: List[Int] = List(3, 4, 5)
l1.dropRight(1) //> res8: List[Int] = List(1, 2, 3, 4)
//--除了一个元素开始
l1.tail(3) //> res9: Int = 5
//判断是否是一个空的List
l1.isEmpty //> res10: Boolean = false
l5.isEmpty //> res11: Boolean = true
//--连接多个List
List.concat(l1,l2) //> res12: List[Int] = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
//--创建一个指定元素重复的数量的List,可以用来生成测试数据
List.fill(5)("a") //> res13: List[String] = List(a, a, a, a, a)
//--通过给定的匿名函数来创建List
val l7 = List.tabulate(5)(x=>x*2) //> l7 : List[Int] = List(0, 2, 4, 6, 8)
//--根据下标获取里列表值
val l9 = l1.apply(1) //> l9 : Int = 2
val v10 = l1(1) //> v10 : Int = 2
//--查看列表是否包含某个列表
val l11 = l1.contains(5) //> l11 : Boolean = true
//--将列表中的元素复制到数组中
val a1 = new Array[Int](3) //> a1 : Array[Int] = Array(0, 0, 0)
val l12 = l1.copyToArray(a1,0,a1.length) //> l12 : Unit = ()
a1 //> res14: Array[Int] = Array(1, 2, 3)
//--去重
val l13=List(1,1,2,2,3) //> l13 : List[Int] = List(1, 1, 2, 2, 3)
val l14 = l13.distinct //> l14 : List[Int] = List(1, 2, 3)
//--根据指定的匿名函数,判断这个元素是否存在
val l15 = l13.exists(x => x%2==0 ) //> l15 : Boolean = true
//--输出l13里面的所有偶数
val l16 = l13.filter ( x => x%2 == 0) //> l16 : List[Int] = List(2, 2)
//--遍历
val l17 = l13.foreach( x => println(x) ) //> 1
//| 1
//| 2
//| 2
//| 3
//| l17 : Unit = ()
//
l13.indexOf(1,0) //> res15: Int = 0
//--取交集
val l18=List(1,2,3,4,5) //> l18 : List[Int] = List(1, 2, 3, 4, 5)
val l19=List(4,5,6,7,8) //> l19 : List[Int] = List(4, 5, 6, 7, 8)
val l20=l18.intersect(l19) //> l20 : List[Int] = List(4, 5)
//-把元素里面的所有元素转化成String类型
val l21 = l18.map { x => x*2 } //> l21 : List[Int] = List(2, 4, 6, 8, 10)
val l22 = l19.mkString(",") //> l22 : String = 4,5,6,7,8
//升序排序
val l23 = List(1,3,6,2,9,8) //> l23 : List[Int] = List(1, 3, 6, 2, 9, 8)
val l24 = l23.sorted //> l24 : List[Int] = List(1, 2, 3, 6, 8, 9)
//降序排序
val l25 = l23.sortBy{ x => -x } //> l25 : List[Int] = List(9, 8, 6, 3, 2, 1)
val l26 = List(Array(1,15),Array(2,29),Array(3,30))
//> l26 : List[Array[Int]] = List(Array(1, 15), Array(2, 29), Array(3, 30))
//--按照年龄排序
//
val l27 = l26.sortBy{ a2 => a2(1)} //> l27 : List[Array[Int]] = List(Array(1, 15), Array(2, 29), Array(3, 30))
//--运算
//--1+2=?
//--?+3=?
l23.reduceLeft((a:Int,b:Int)=>a+b) //> res16: Int = 29
//--计算1到10的阶乘
1 to 10 reduceLeft(_*_) //> res17: Int = 3628800
//--集合之间的转换
//--可以用在方法的共享上
val l28 = l18.toArray //> l28 : Array[Int] = Array(1, 2, 3, 4, 5)
}
Set集合
object Demo18 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--声明一个定长的Set集合
val l1 = Set(1,2,3,4,5) //> l1 : scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
//--声明一个变长的Set
val s2 = scala.collection.mutable.Set(1,2,3,4,5)//> s2 : scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4)
//-0取交集
val s3 = Set(1,3,4) //> s3 : scala.collection.immutable.Set[Int] = Set(1, 3, 4)
val s4 = Set(2,3,4) //> s4 : scala.collection.immutable.Set[Int] = Set(2, 3, 4)
val s5 = s3&s4 //> s5 : scala.collection.immutable.Set[Int] = Set(3, 4)
val s6 = s3.intersect(s4) //> s6 : scala.collection.immutable.Set[Int] = Set(3, 4)
//--取差值
val s7 = s4.diff(s3) //> s7 : scala.collection.immutable.Set[Int] = Set(2)
val s8 = s3&~s4 //> s8 : scala.collection.immutable.Set[Int] = Set(1)
//--合并两个集合
val s9 = s3++s4 //> s9 : scala.collection.immutable.Set[Int] = Set(1, 3, 4, 2)
//--根据指定的匿名函数,返回元素个数
val s10 = s4.count {x => x%2 !=0 } //> s10 : Int = 1
//--拆分,按照指定的数,拆分成两个Set集合
val s11 = Set(1,2,3,4,5) //> s11 : scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
s11.splitAt(2)._1 //> res0: scala.collection.immutable.Set[Int] = Set(5, 1)
}
Map集合
package com.biem.test
object test07 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val m1 = Map("yao"->18,"lan"->28,"simayi"->48) //> m1 : scala.collection.immutable.Map[String,Int] = Map(yao -> 18, lan -> 28,
//| simayi -> 48)
val m2 = for(i<-m1)println(i) //> (yao,18)
//| (lan,28)
//| (simayi,48)
//| m2 : Unit = ()
//--掌握使用下面的方式遍历map,其中(k,v)就是占位符,不是固定的
for((k,v)<-m1)println(v) //> 18
//| 28
//| 48
}
Tuple集合
object Demo19 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val t1 = (1,2,3,4) //> t1 : (Int, Int, Int, Int) = (1,2,3,4)
val t2 =(1,List(1,2,3),Array(1,2,3),"hello") //> t2 : (Int, List[Int], Array[Int], String) = (1,List(1, 2, 3),Array(1, 2, 3)
//| ,hello)
//--Tuple得取值
t1._3 //> res0: Int = 3
//--需求:取t2当中的Array里面的3
t2._3(2) //> res1: Int = 3
val t3 =(1,2,"hello",(1,2,(3,4))) //> t3 : (Int, Int, String, (Int, Int, (Int, Int))) = (1,2,hello,(1,2,(3,4)))
//--要求:取3
t3._4._3._1 //> res2: Int = 3
val a1 = Array(("hello",1),("word",1),("scala",1))
//> a1 : Array[(String, Int)] = Array((hello,1), (word,1), (scala,1))
//要求:操作a1,返回一个新的数字a2("hello","word","scala")
val a2 = a1.map{x=>x._1} //> a2 : Array[String] = Array(hello, word, scala)
//--要求:把a2变回a1
val a4 = Array("tom,23,m","rose,25,w","jim,19,w")
//> a4 : Array[String] = Array(tom,23,m, rose,25,w, jim,19,w)
//--要求:操作a4,并返回一个新的数组((tom,23,m),(rose,25,w),(jim,19,w))
val a5 = a4.map{line=>{
val info = line.split(",")
val name = info(0)
val age = info(1).toInt
val gender = info(2)
(name,age,gender)
}} //> a5 : Array[(String, Int, String)] = Array((tom,23,m), (rose,25,w), (jim,19,
//| w))
val a6 = for(i<- 0 to 2){
}
}
Scala函数
函数格式
private/protected def 函数名(参数列表):返回值声明 = {函数体}
函数的声明
Scala函数通过 def 关键字定义,def前面private,
protected来控制其访问权限。
注意:没有public。不写默认为public的。
此外也可跟上override,final等关键字修饰。
函数的返回值
1.函数体中return关键字往往可以省略掉,一旦省略掉,
函数将会返回整个函数体中最后一行表达式的值,
这也要求整个函数体的最好一行是正确类型的值的表达式。
2.大部分时候scala都可以通过 = 符号来自动判断返回值的类型,
所以通常返回值类型声明可以省略。
注意:如果因为省略了返回值类型造成歧义,则一定要写上返回值声明。
3.如果函数只有一行内容,则包裹函数体的大括号可以省略
4.如果返回值类型是UNIT,则另一种写法是可以去掉返回值类型和等号,
把方法体写在花括号内,而这时方法内无论返回什么,返回值都是UNIT。
函数的种类
成员函数
函数被使用在类的内部,作为类的一份子,成为类的成员函数
本地函数(内嵌在函数内的函数)
函数内嵌的函数成为本地函数,这样的函数外界无法访问
高阶函数
函数可以作为方法的参数进行传递和调用
函数的声明和调用
package com.biem.function
/**
知识点1:函数的声明和调用
1、scala通过def关键字来声明函数
def 函数名(参数列表):返回值类型={方法体}
2、scala可以根据方法体的方回执,自动的推断出函数的返回值类型
3、scala函数是通过=来自动推断的,如果没有这个=,则返回值类型一律为Unit类型
4、scala函数默认修饰符就是public
此外还可以在def在前使用private、protected来修饰
**/
package com.biem.function
class Person {
//--成员函数:定义在类内部的函数
def say()={
println("hello")
//--本地函数:定义在函数内部的函数
def cook={
println("cook food")
}
}
}
object test09{
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
def f1():Unit={} //> f1: ()Unit
def f2():String={
"hello,scala"
} //> f2: ()String
def f3()={
123
} //> f3: ()Int
def f4(){
"hello"
} //> f4: ()Unit
def f5(a:Int,b:Int)=a+b //> f5: (a: Int, b: Int)Int
val i1=f5(2,3) //> i1 : Int = 5
def f6(a:String)={
a.split(",")
} //> f6: (a: String)Array[String]
//--scala里面的泛型不同于java<>,是Array[]的形式
val s1=f6("hello,scala") //> s1 : Array[String] = Array(hello, scala)
//--定义一个函数:接受一个整型数组,作用是遍历此数组,并打印
def f7(a:Array[Int])={
for(i<-a)println(i)
} //> f7: (a: Array[Int])Unit
f7(Array(1,2,3,4,5)) //> 1
//| 2
//| 3
//| 4
//| 5
//--默认参数
//--这里的b和c就是使用了默认参数机制,如果调用这个函数时
//--没有传入b和c,那么就使用这个声明好的默认值[]
//--形式:(形参名:参数类型=默认值)=>c:String="]"
def f8(a:String,b:String="[",c:String="]")={
b+a+c
} //> f8: (a: String, b: String, c: String)String
f8("hello") //> res0: String = [hello]
f8("hellp","!","@") //> res1: String = !hellp@
val p1=new Person() //> p1 : com.biem.function.Person = com.biem.function.Person@6cd8737
p1.say() //> hello
}
函数值(匿名函数)
package com.biem.function
/**
1、匿名函数最大的特点就是没有函数名
2、匿名函数是通过=>把参数列表和方法体连接起来的
3、匿名函数最大的作用就是可以被当做参数进行传递
**/
object test10 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
def f1(a:Int,b:Int)={a+b} //> f1: (a: Int, b: Int)Int
//--声明一个匿名函数
val f2=(a:Int,b:Int)=>{a+b} //> f2 : (Int, Int) => Int = <function2>
f2(2,3) //> res0: Int = 5
def f3(a:Int,b:Int,f:(Int,Int)=>Int)={
f(a,b)
} //> f3: (a: Int, b: Int, f: (Int, Int) => Int)Int
f3(2,3,(a:Int,b:Int)=>{a*b}) //> res1: Int = 6
def f4(a:String,f:(String)=>Array[String])={
f(a)
} //> f4: (a: String, f: String => Array[String])Array[String]
f4("hello,world",(a:String)=>{a.split(",")}) //> res2: Array[String] = Array(hello, world)
def f5(a:Array[Int],f:(Array[Int])=>Unit){
f(a)
} //> f5: (a: Array[Int], f: Array[Int] => Unit)Unit
val f6=(a:Array[Int])=>{
for(i<-a)println(i)
} //> f6 : Array[Int] => Unit = <function1>
f5(Array(1,2,3),f6) //> 1
//| 2
//| 3
}
匿名函数的化简规则
package com.biem.function
/**
知识点3:
1、如果方法体中只有一行代码,则{}可以省略
2、如果匿名函数的参数类型可以自动推断出的话,那么参数类型可以省略
3、如果匿名函数参数列表只有一个,则匿名函数的()可以省略
4、最终化简模式是可以通过_(占位符)来化简->使用条件:每个参数在函数当中仅出现一次才可以使用
5、高阶函数:函数可以作为方法的参数传递或调用
**/
object test11 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
(a:Int,b:Int)=>{a+b} //> res0: (Int, Int) => Int = <function2>
(a:Int,b:Int)=>a+b //> res1: (Int, Int) => Int = <function2>
def f1(a:Int,b:Int,f:(Int,Int)=>Int)={
f(a,b)
} //> f1: (a: Int, b: Int, f: (Int, Int) => Int)Int
f1(2,3,(a:Int,b:Int)=>{a+b}) //> res2: Int = 5
f1(2,3,(a,b)=>a+b) //> res3: Int = 5
f1(2,3,_+_) //> res4: Int = 5
def f2(a:String,f:(String)=>String)={
f(a)
} //> f2: (a: String, f: String => String)String
f2("hello",(a:String)=>a.reverse) //> res5: String = olleh
f2("hello",a=>a.reverse) //> res6: String = olleh
f2("hello",_.reverse) //> res7: String = olleh
val a1=Array(1,2,3) //> a1 : Array[Int] = Array(1, 2, 3)
a1.foreach{(x:Int)=>{println(x)}} //> 1
//| 2
//| 3
a1.foreach{x=>println(x)} //> 1
//| 2
//| 3
a1.foreach{println(_)} //> 1
//| 2
//| 3
a1.filter{(x:Int)=>{x%2==0}} //> res8: Array[Int] = Array(2)
a1.filter{x=>x%2==0} //> res9: Array[Int] = Array(2)
a1.filter{_%2==0} //> res10: Array[Int] = Array(2)
}
scala的柯里化
package com.biem.function
/**
**/
object test14 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--柯里化技术,允许将接受的多个参数的函数
//--转变成结构单一参数的函数
def f1(a:Int,b:Int)={a+b} //> f1: (a: Int, b: Int)Int
def f11(a:Int)(b:Int)={a+b} //> f11: (a: Int)(b: Int)Int
def f2(a:Int,b:Int,c:Int)={a+b+c} //> f2: (a: Int, b: Int, c: Int)Int
def f21(a:Int)(b:Int)(c:Int)={a+b+c} //> f21: (a: Int)(b: Int)(c: Int)Int
def f22(a:Int,b:Int)(c:Int)={a+b+c} //> f22: (a: Int, b: Int)(c: Int)Int
def f23(a:Int)(b:Int,c:Int)={a+b+c} //> f23: (a: Int)(b: Int, c: Int)Int
def f3(a:Int,b:Int,f:(Int,Int)=>Int)={f(a,b)} //> f3: (a: Int, b: Int, f: (Int, Int) => Int)Int
def f31(a:Int)(b:Int)(f:(Int,Int)=>Int)={f(a,b)}//> f31: (a: Int)(b: Int)(f: (Int, Int) => Int)Int
def f32(a:Int,b:Int)(f:(Int,Int)=>Int)={f(a,b)} //> f32: (a: Int, b: Int)(f: (Int, Int) => Int)Int
def f33(a:Int)(b:Int,f:(Int,Int)=>Int)={f(a,b)} //> f33: (a: Int)(b: Int, f: (Int, Int) => Int)Int
//--f32这种结构,参数有两个部分,一部分是普通函数
//--另一部分是匿名函数
//--称这样的结构叫做自建控制结构
//--所以说柯里化技术允许用户创建自建控制结构
f32(2,3)((a:Int,b:Int)=>{a+b}) //> res0: Int = 5
}
递归
package com.biem.function
/**
**/
object test12 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--用scala的递归函数,判断斐波那契数列第N项的数字是多少
//--2 3 5 8 13 21 34
//--写递归函数的技巧
//--1、找出函数的关系,找出的是项与项之间存在什么样的函数关系
//--2、找出递归函数结束条件
//--函数关系:f(n)=f(n-1)+f(n-2)
//--结束条件:f(0)=2 f(1)=3
//--scala递归函数:必须显示的声明返回值类型,不能自动推断
//--此外:结束条件的返回值,必须用return关键字返回
def f1(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
else f1(n-1)+f1(n-2)
} //> f1: (n: Int)Int
f1(2) //> res0: Int = 5
//--2 3 4 9 8 27 16 81->第N项的数字是多少
//--0 1 2 3 4 5 6 7
//--结束条件:f(0)=2 f(1)=3
//--如果是偶数项:f(n)=2*f(n-2)
//--如果是奇数项:f(n)=3*f(n-2)
def f2(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
if(n%2==0) 2*f2(n-2)
else 3*f2(n-2)
} //> f2: (n: Int)Int
f2(9) //> res1: Int = 243
lazy-懒值
/**
**/
object test13 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val v1=100 //> v1 : Int = 100
//--声明一个懒值,特点:声明的时候不是马上就赋值
//--而是被调用的时候才会赋值
//--注意:lazy只能修饰常量(val),不能修饰变量(var)
lazy val v2=100 //> v2: => Int
println(v2) //> 100
}
for yield
//--操作一个集合类型,并返回一个新集合
//--scala的集合类型包含:Array,List,Range,Map,Set,Tuple
//--for yield表达式,操作的是什么集合类型,返回的就是什么集合类型
val a2 = Array(1,2,3) //> a2 : Array[Int] = Array(1, 2, 3)
val a3=for(i<-a2)yield{i*2} //> a3 : Array[Int] = Array(2, 4, 6)
val l1=List(1,2,3) //> l1 : List[Int] = List(1, 2, 3)
val l2=for(i<-l1)yield{i+2} //> l2 : List[Int] = List(3, 4, 5)
groupBy
object test20 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val l1 = List("hello","hello","word","hello","world")
//> l1 : List[String] = List(hello, hello, word, hello, world)
//--groupBy:按照指定的条件做分组聚合,返回的是一个map数据结构
//--map的key就是指定的条件元素,map的value就是相同元素组成的List
l1.groupBy{x=>x} //> res0: scala.collection.immutable.Map[String,List[String]] = Map(world -> Lis
//| t(world), word -> List(word), hello -> List(hello, hello, hello))
val l2 = List(("bj",1),("sh",2),("bj",3),("sh",4))
//> l2 : List[(String, Int)] = List((bj,1), (sh,2), (bj,3), (sh,4))
//--要求:操作l2,按照地区做集合
l2.groupBy{x=>x._1} //> res1: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(bj ->
//| List((bj,1), (bj,3)), sh -> List((sh,2), (sh,4)))
}
break continue
package com.biem.test
import util.control.Breaks._
object test08 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--注意:使用break时需要导包:import util.control.Breaks._
//--scala中是没有continue关键字的
//--实现方式:在breakable()里的break相当于continue
for(i<-1 to 9){
breakable(
if(i==7){
break
}else{
println(i)
}
) //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
//| 8
//| 9
}
//--如果breakable()在for循环里面,break是continue
//--如果breakable()在for循环外面,break是跳出循环的意思
breakable(
for(i<-1 to 9){
if(i==6){
break
}else{
println(i)
}
}
) //> 1
//| 2
//| 3
//| 4
//| 5
//def f1():Unit={}
}