1.class、object、case class、case object间的简单区别:2.Case Class3.模式匹配4.隐式转换implicit5.可扩展性与高阶函数6.Scala泛型7.Scala集合
1.数组2.序列(有序)3.集合(不能重复且无序)4.Map(key不可重复,value可以重复)5.Tuple6.队列 8.部分常用方法
1.class、object、case class、case object间的简单区别:2.Case Class
case class A(a:Int)
case class B(b:Int)
def classMath (x:AnyRef):Unit = {
x match {
case A(a) => println("A:"+a)
case B(b) => println("A:"+b)
case A => println(A.apply(100))
}
}
val a = A(1)
val b = B(2)
classMath(a) //A:1
classMath(b) //A:2
classMath(A) //A(100)
3.模式匹配
//scala模式匹配
//匹配对象包含常量、变量、类型、对象、数组、列表、元组、特殊匹配、样例类等;
//其中在匹配类型等情形下,可以通过类似a:Int => a... 来对变量做相关性操作;
//特殊匹配包含spark中常用写法,如map等算子常用编程技巧,也有如直接给变量命名等操作,比如:
//val (id,name,age):(String,String,Int) = ("123","cx",25)
//println(name) //cx
4.隐式转换implicit
implicit
三种用法:
1、隐式参数
当我们在定义方法时,可以把最后一个参数列表标记为implicit,表示该组参数是隐式参数。一个方法只会有一个隐式参数列表,置于方法的最后一个参数列表。如果方法有多个隐式参数,只需一个implicit修饰即可。 当调用包含隐式参数的方法时,如果当前上下文中有合适的隐式值,则编译器会自动为改组参数填充合适的值。如果没有编译器会抛出异常。当然,标记为隐式参数的我们也可以手动为该参数添加默认值。
例1: //这里的group:Float即是隐式参数列表 def animal(n:Int)(implicit group:Float) : Float = n * group //这一隐式值也是Float类型值,那么就可以作为隐式参数的合适值进行赋值。 implicit val groupNum = 10F val num = animal(10) println(num) //100.0
2、隐式函数
使用隐含转换将变量转换成预期的类型是编译器最先使用 implicit 的地方。在默认情况下,当编译器发现无效的方法调用时(比如用类型X去调用Y但直观上二者之间并没有相关定义),它就在当前作用域查找是否定义了从类型X到类型Y的隐式定义,见例1;
在某些情况下,我们甚至可以基于隐式函数,来实现我们自己想要的编程语言,例2给了一个展示;
例1:
val i: Int = 3.5 //直接报错
//加上这句:
implicit def double2Int(d: Double) = d.toInt
//报错消失
val i: Int = 3.5
println(i) //i=3
例2:
class DateHelper(offset: Int) {
def days(when : String): LocalDate = {
val today = LocalDate.now()
when match {
case "ago" => today.minusDays(offset)
case "from_now" => today.plusDays(offset)
case _ => today
}
}
}
implicit def convertInt2dateHealper (offset: Int)
: DateHelper = new DateHelper(offset)
val ago = "ago"
val from_now = "from_now"
//这里其实就省略了convertInt2dateHealper方法
val past = 2 days ago //也即是2 days(ago)
//相当于val past1 = convertInt2dateHealper(2).days(ago)
val appointment = 5 days from_now
println(past) //2022-01-19
println(appointment) //2022-01-26
3、隐式类
直接用implicit修饰类,但不同于正常的类,隐式类不能是一个独立的类,它必须要在一个单例对象、类或特质中。
直接用来修饰一个独立的类时,编译器会报错:
还是运用例2的例子来讲:
object DateUdf {
val ago = "ago"
val from_now = "from_now"
implicit class DateHelper(offset:Int){
import java.time.LocalDate
def days(when:String):LocalDate = {
val today = LocalDate.now()
when match {
case "ago" => today.minusDays(offset)
case "from_now" => today.plusDays(offset)
case _ => today
}
}
}
def main(args: Array[String]): Unit = {
val past = 2 days ago
val appointment = 5 days from_now
println(past) //2022-01-19
println(appointment) //2022-01-26
}
}
5.可扩展性与高阶函数
Scala允许在方法的参数中设置一个没有名称只有参数和实现的函数,例:
object testFunc {
//这里的codeBlock: Int => Int实际上就是值一个实现的函数,函数输入输出都为Int类型数;
def totalResultOverRange (number:Int, codeBlock: Int => Int) = {
var result = 0
for (i <- 1 to number){
result += codeBlock(i)
}
result
}
def main(args: Array[String]): Unit = {
//这里实际上就运用刚才所讲的需要实现的函数
println(totalResultOverRange(10,i => if (i % 2 == 0) 0 else i))
}
}
结果为:25(即1到10间的奇数和)
6.Scala泛型
//泛型
def decode[T: Manifest](json: String, typeRef: TypeReference[T]): T = {
mktMapper.readValue(json, typeRef)
}
//泛型上下界:
<: 上边界限定
下边界限定 >:
T <% U 视图限定 : 表示必须要求上下⽂有⼀个隐式转换能够将T转换为U类型。
//如果直接按照下面这么写会报错:
package com.atguigu.apitest.sinttest
import scala.io.Codec.fallbackSystemCodec.name
object Test {
def main(args: Array[String]): Unit = {
//这里测试的是String -> People的转化
read(new People("25"))
}
def read [T <% People](t:T) : Unit = {
t.character()
}
}
class Book (name:String) {
def character():Unit = {
println(s"$name" + "真好看")
}
}
class People(age:String) extends Book(name:String) {
override def character() : Unit = {
println(s"$age"+"岁的人喜欢看老人与海")
}
}
//以下内容必须添加,否则无法编译通过;
//还需要加上一个隐式类转化才行:
object MyImplicit {
implicit def b2c (name:String):People={
new People(name)
}
}
7.Scala集合
Scala的集合有三大类:序列Seq、集Set、映射Map,所有集合都扩展自Iterable特质。对于所有的集合类,Scala都同时提供了可变和不可变的版本。
可变集合和不可变集合使用包名区分:scala.collection.immutable scala.collection.mutable
不可变 可变
数组 Array ArrayBuffer
序列(List) Seq、List ListBuffer
集合 Set mutable.Set
映射 Map mutable.Map
元组 Tuple
1.数组
//不可变数组 val array = new Array[Int](2) //默认值为0 val arrayS = new Array[String](5) //默认值为null ++: , .++ ,++表示array+array,数组(列表)+数组(列表)等 array(list) :+ a,a +: array(list)表示元素添加到数组(列表)后,分别元素添加到数组(列表)前 //可变数组 val arrayBuffer = ArrayBuffer(1,2,3,4) arrayBuffer.append(4) //二者转化: array.toBuffer() arrayBuffer.toArray()2.序列(有序)
//不可变
List、Seq
空集合中添加元素用::
val list1 = List(1,2,3)
val list2 = List(4,5)
val list3 = list1 ++ list2 //List(1,2,3,4,5)
val list4 = list3 :: Nil
list4.foreach(println) //List(1,2,3,4,5)
将一个List集合作为一个整体加入到空集合中
println(1::2::3::4::list3::Nil) //List(1, 2, 3, 4, List(1, 2, 3, 4, 5))
//可变
ListBuffer
append、drop、dropRight、insert、update、remove等方法
//部分常用方法:
val list1 = List(1,2,5)
println(list1.zipWithIndex) //List((1,0), (2,1), (5,2))
val list2 = List(4,5)
println(list1.zip(list2)) //List((1,4), (2,5)) 少的那一个List就会少进行zip操作
// 集合并集
println("union => " + list.union(list1))
// 集合交集
println("intersect => " + list.intersect(list1))
// 集合差集
println("diff => " + list.diff(list1))
//集合切分
val list = List(1,2,3,4,5,6,7,8,9)
println("splitAt => " + list.splitAt(2)) //splitAt => (List(1, 2),List(3, 4, 5, 6, 7, 8, 9))
//集合最大、小值(max,min),过滤(filter),分组(groupBy),映射(map),打平(flatten),自定义扁平化(flatMap),排序(sortBy)
val list3 = List("hello","world","scala","hello","spark")
val groupMap = list3.groupBy((s: String) => {
s.substring(0, 1)
})
println(groupMap) //Map(w -> List(world), h -> List(hello, hello), s -> List(scala, spark))
//对上面的结果,统计w和h和s开头的单词的个数,然后排序
val sumList = groupMap.toList.map(t => {
val size = t._2.size
(t._1, size)
})
println(sumList) //List((w,1), (h,2), (s,2))
//排序默认是升序排序
//更改为降序排序使用.Ordering.Int.reverse
println(sumList.sortBy(t => t._2)) //List((w,1), (h,2), (s,2))
println(sumList.sortBy(t => t._2)(Ordering.Int.reverse)) //List((h,2), (s,2), (w,1))
3.集合(不能重复且无序)
//不可变
val set = Set(1, 2, 3, 4, 5, 6, 7)
//1 添加元素
//不可变集合Set不支持添加修改,可以删除和添加,但是是生成新的Set
val set1 = set + 10
val set2 = set.+(11, 12) //部分其他计算逻辑未展示
println(set) //Set(5, 1, 6, 2, 7, 3, 4)
println(set1) //Set(5, 10, 1, 6, 2, 7, 3, 4)
println(set2) //Set(5, 1, 6, 2, 12, 7, 3, 11, 4)
//2 删除元素
val set3 = set1 - 10
println(set3) //Set(5, 1, 6, 2, 7, 3, 4)
//3 遍历集合Set
set.foreach(println)
println(set.mkString(",")) //5,1,6,2,7,3,4
//可变
val set = mutable.Set(1,2,3,4,5)
val set1 = mutable.Set(3,4,5,6,7)
set.add(6)
println(set) //Set(1, 5, 2, 6, 3, 4)
set.remove(1)
println(set) //Set(5, 2, 6, 3, 4)
println(set & set1) //交集 Set(5, 2, 6, 3, 4)
println(set &~ set1) //差集 Set(2)
4.Map(key不可重复,value可以重复)
//不可变map,涉及计算方法包括+、-、updated等
val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
val map1 = Map(("aa", 11), ("bb", 22), ("cc", 33))
val map2 = map + (("ee", 10))
val map3 = map1 + ("ee" -> 10)
println(map2) //Map(a -> 1, b -> 2, c -> 3, ee -> 10)
println(map3) //Map(aa -> 11, bb -> 22, cc -> 33, ee -> 10)
val map4 = map2 - "ee"
println(map4) //Map(a -> 1, b -> 2, c -> 3)
val map5 = map2.updated("aa",10)
println(map5) //Map(a -> 1, b -> 2, c -> 3, aa -> 10, ee -> 10)
// 创建空Map
val empty = Map.empty
println(empty)
// 获取Map的指定key的value值
println(map("a"))
// 获取可能的key值
val maybeInt: Option[Int] = map.get("b")
//判断key值是否存在;不存在None;存在Some(value值)
println(maybeInt)
// 获取可能存在的值,如果不存在就使用默认的值
println(map.getOrElse("aaa", 11))
//可变map,多增加put、remove、iterator、clear等方法
val map = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
map.put("d",4)
println(map) //Map(b -> 2, d -> 4, a -> 1, c -> 3)
map.remove("a")
println(map) //Map(b -> 2, d -> 4, c -> 3)
val list = map.toList
println(list) //List((b,2), (d,4), (c,3))
val iterator = map.iterator
while (iterator.hasNext){
println(iterator.next()) //(b,2),(d,4),(c,3)
}
//Map的key的迭代器
val iterator1 = map.keysIterator
val iterator2 = map.keys.iterator
//Map的value的迭代器
val iterator3 = map.valuesIterator
val iterator4 = map.values.iterator
// 清除Map
map.clear()
println(map) //Map()
5.Tuple
val tuple = (1,"chenxu",'a',24)
println(tuple._1) //1
println(tuple._2) //chenxu
println(tuple._3) //a
println(tuple._4) //24
//1 采用数据在元组中的索引访问
println(tuple.productElement(0)) //1
//2 采用迭代器的方式访问
val iterator = tuple.productIterator
while (iterator.hasNext){
println(iterator.next()) //1 chenxu a 24
}
6.队列
val que = new mutable.Queue[String]()
// 添加元素
que.enqueue("a", "b", "c")
val que1: mutable.Queue[String] = que += "d"
println(que1) //Queue(a, b, c, d)
println(que eq que1) //true 二者仍然调用的是同一个que
// 获取元素
println(que.drop(2)) //Queue(c, d) 但实际上并没有在原que中删除c,d元素
println(que.dequeue()) //a
println(que.dequeue()) //b
println(que.dequeue()) //c
println(que.dequeue()) //d
8.部分常用方法
1.stripMargin
代码实例: val speech = ”””Let us scala and |learn spark oh”””.stripMargin 运行的结果为: Let us scala and learn spark oh 主要作用:用来自动过滤"|"符号,对语言进行自动分行。



