===================== Scala语言的高级特性 ========================
一、Scala的集合
1、可变集合mutable

不可变集合immutable

//不可变集合
val math = scala.collection.immutable.Map("Alice"->80,"Bob"->90)
//可变集合
val chinese = scala.collection.mutable.Map("Alice"->80,"Bob"->90)
//1. 获取集合中的值
chinese("Bob")
if(chinese.contains("Bob")){
chinese("Bob")
}else{
-1
}
//简写
chinese.getOrElse("Bob",-1)
//2、修改更新可变集合中的值
chinese("Bob")=100
//添加新的元素
chinese += "Jerry" ->90
//删除元素
chinese -= "Bob"
//迭代
for (s <- chinese) println(s)
chinese.foreach(println)

2、列表:List

import scala.collection.mutable

//可变 不可变列表
//不可变:List var nameList = List("Mary","Tom","Mike")
var intList = List(1,2,3,4)
var nullList:List[Nothing] = List()
//二维
var din:List[List[Int]] = List(List(1,2,3),List(4,5,6))
println("第一个人的名字: "+nameList.head)
println("除去第一个: "+nameList.tail) //可变列表(LinkedList)
val myList = mutable.LinkedList(1,2,3,4,5,6)
//每个元素乘2
//类似PLSQL:cursor 游标
var cur = myList
//当指针!=null时 Nil:Scala的null值
while (cur != Nil){
//对当前值*2
cur.elem = cur.elem*2
//指向下一个值
cur = cur.next } //结果
println(myList) //LinkedList(2, 4, 6, 8, 10, 12)

3、序列: 常用的序列: Vector、Range

//序列:Vector,Range
//Vector:带下标的序列
val v = Vector(1,2,3,4,5,6)
//返回第一个满足条件的元素
v.find(_> 3)
//更新下标为2
v.updated(2,100) //Range:整数序列
println("第一种写法: "+Range(0,5))
println("第二种写法: "+(0 until 5))
println("第三种写法: "+(0 to 4)) ('0' to '9') ++ ('A' to 'Z') 1 to 5 toList

运行结果:

v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5, 6)

res0: Option[Int] = Some(4)

res1: scala.collection.immutable.Vector[Int] = Vector(1, 2, 100, 4, 5, 6)

第一种写法: Range(0, 1, 2, 3, 4)
res2: Unit = ()
第二种写法: Range(0, 1, 2, 3, 4)
res3: Unit = ()
第三种写法: Range(0, 1, 2, 3, 4)
res4: Unit = () res5: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) res6: List[Int] = List(1, 2, 3, 4, 5)

4、集(Set): 是不重复元素的集合,默认的实现:HashSet

import scala.collection.mutable

//集(Set):不重复的元素集合,默认实现:HashSet
var s1 = Set(10,2,0,1)
s1 += 0
s1
s1 += 100
s1
var weeksDay = mutable.LinkedHashSet("星期一","星期二")
weeksDay + "星期五"
weeksDay.contains("星期二")
var s2 = mutable.SortedSet(1,2,3,100,10,4) //判断一个Set是否是另一个Set的
Set("星期一","星期二").subsetOf(weeksDay)
var set1 = Set(1,2,3,4,5,6)
var set2 = Set(5,6,7,8,9,10)
//并交差
set1 union set2
set1 intersect set2
set1 diff set2

运行结果:

import scala.collection.mutable

s1: scala.collection.immutable.Set[Int] = Set(10, 2, 0, 1)
res0: Unit = ()
res1: scala.collection.immutable.Set[Int] = Set(10, 2, 0, 1)
res2: Unit = ()
res3: scala.collection.immutable.Set[Int] = Set(0, 10, 1, 2, 100)
weeksDay: scala.collection.mutable.LinkedHashSet[String] = Set(星期一, 星期二)
res4: scala.collection.mutable.LinkedHashSet[String] = Set(星期一, 星期二, 星期五)
res5: Boolean = true
s2: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 4, 10, 100) res6: Boolean = true
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)
set2: scala.collection.immutable.Set[Int] = Set(5, 10, 6, 9, 7, 8) res7: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)
res8: scala.collection.immutable.Set[Int] = Set(5, 6)
res9: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

5、模式匹配:match

相当于Java的 instanceof、switch case
(*)Scala的一个强大的switch case语句
(*)类型的检查

//模式匹配
var ch1 = '-'
var flag = 0
ch1 match {
case '+' => flag = 1
case '-' => flag = -1
case _ => flag = 0
}
println(flag) //2.Scala的守卫:匹配某种类型的所有值
var ch2 = '6'
var digit:Int = -1
ch2 match {
case '+' => println("+")
case '-' => println("-") }

运行结果:

ch1: Char = -
flag: Int = 0
res0: Unit = () -1
res1: Unit = () ch2: Char = 6
digit: Int = -1
scala.MatchError: 6 (of class java.lang.Character)
at #worksheet#.#worksheet#(Demo7.sc0.tmp:8)

6、样本类:case class

好处:支持模式匹配
使用样本类来定义DataFrame(表)的Schema(表的结构) -----> Spark SQL

//使用样本类支持模式匹配: 类似: instanceof

class Vehicle

case class Car(name:String) extends Vehicle
case class Bike(name:String) extends Vehicle //定义一个Car对象
var aCar:Vehicle = new Car("这是汽车")
aCar match {
case Car(name) => println("这是一辆汽车")
case Bike(name)=> println("这是一辆自行车")
case _ => println("其他类型")
}

运行结果:这是一辆汽车

二、Scala的泛型: T ----> 重要
1、泛型类: [T]

package main.scala

/**
* Created by YOGA on 2018/2/5.
*/
class GenericClass[T]{
private var content:T = _
def set(value:T) = {
content = value
}
def get():T = {content}
}
object GenericClass {
def main(args: Array[String]): Unit = {
//Int类型
var intGeneric = new GenericClass[Int]
intGeneric.set(123)
println("得到的值: "+intGeneric.get())
//String类型
var stringGeneric = new GenericClass[String]
stringGeneric.set("Hello")
println("得到的值:"+stringGeneric.get())
}
}

运行结果:

得到的值: 123
得到的值:Hello

2、泛型函数
创建一个函数,功能:创建一个Int类型的数组

*代表可变参数

def mkIntArray(elems:Int*) = Array[Int](elems:_*)
mkIntArray(1,2,3,4,5)

创建一个函数,功能:创建一个String类型的数组

def mkStringArray(elems:String*) = Array[String](elems:_*)
mkStringArray("Tom","Mary","Mike")

问题:能否创建一个通用的函数,既能创建Int类型数组,也能创建String类型的数组
在泛型函数中:T有要求:必须是ClassTag类型

import scala.reflect.ClassTag
def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
mkArray(1,2,3,4,5)
mkArray("Tom","Mary","Mike")

ClassTag: 表示执行Scala程序时的运行信息,该例子中,表示数据的类型

3、上界和下界:规定泛型的取值范围
举例:
(1) 普通数据类型
int x 范围
100 <= x <= 200
下界 上界

(2)规定:泛型的取值范围
继承关系
A ---> B ---> C ---> D

D <: y泛型 <: B ====> 表示:y的类型只能是:B C D

概念
上界:定义 S <: T,表示S的类型必须是T的子类
下界:定义 U >: T 表示U的类型必须是T的父类

package main.scala
//上界
//父类
class Vehicle2{
def drive() = {println("Driving")}
}
//子类
class Car2 extends Vehicle2{
override def drive():Unit = {println("Car Driving")}
}
class Bike2 extends Vehicle2{
override def drive():Unit = {println("Bike Driving")}
}
object ScalaUpperBound {
//泛型
def takeVehicle[T <: Vehicle2](v:T) = {v.drive()} def main(args: Array[String]) {
var v1:Vehicle2 = new Vehicle2
takeVehicle(v1)
var v2:Car2 = new Car2
takeVehicle(v2) }
}

运行:

Driving
Car Driving

4、视图界定:是上界和下界的一个扩展
概念:适用范围更广泛
以上界为例 <:
接收除了所有的子类,还允许接收隐式转换过去的类型
定义:<%

看个例子: 定义一个函数完成两个字符串的拼加

def addTwoString[T <: String](x:T,y:T) = {println(x+"****"+y)}

调用:

addTwoString("Hello","World")

再调用一次:会报错

 addTwoString(100,200) ====> 100*****200

使用视图界定重新来定义

def addTwoString[T <% String](x:T,y:T) = {println(x+"****"+y)}

表示T的类型:
(1)String和String的子类
(2)还可以是可以转换成String的类型

重新调用:

addTwoString(100,200)
error: No implicit view available from Int => String.

视图界定的时候:一定有一个转换规则(隐式转换函数)

implicit def int2String(n:Int):String = {n.toString}
addTwoString(100,200)

执行过程: (1) 调用隐式转换函数int2String: int ====> String
100 ---> "100"
200 ---> "200"
(2) 再调用addTwoString

5、协变、逆变:看成是视图界定的一个扩展

  协变:一个泛型类接收的泛型参数的值可以是本身的类型或者是子类的类型

逆变:一个泛型类接收的泛型参数的值可以是本身的类型或者是父类的类型

package main.scala.demo1

//Scala的协变: 一个泛型类接收的泛型参数的值可以是本身的类型或者是子类的类型
// 在泛型前 + //动物
class Animal{} //子类:鸟
class Bird extends Animal //子类:麻雀
class Sparrow extends Bird //类:吃东西(动作)
class EatSomething[+T](t:T){} object DemoClass1 { def main(args: Array[String]): Unit = {
//创建一个鸟吃东西的对象
var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird) //创建一个动物吃东西的对象
//var c2:EatSomething[Animal] = new EatSomething[Animal](new Animal)
//问题:能否将c1付给c2?
//原因:尽管Bird是Animal的子类,但是EatSomething[Bird]不是EatSomething[Animal]的子类
//方法:把EatSomething[Bird] 变成 EatSomething[Animal] 子类 方法是添加一个泛型类 class = EatSomething[+T](t:T){}
var c2:EatSomething[Animal] = c1 //再举个例子
var c3:EatSomething[Sparrow] = new EatSomething[Sparrow](new Sparrow)
var c4:EatSomething[Animal] = c3
}
}
package main.scala.demo1

//Scala的逆变: 一个泛型类接收的泛型参数的值可以是本身的类型或者是父类的类型
// 语法: -号 //动物
class Animal{} //子类:鸟
class Bird extends Animal //子类:麻雀
class Sparrow extends Bird //定义吃东西的类
class EatSomething[-T](t:T){} object DemoClass2 {
def main(args: Array[String]): Unit = {
//创建一个鸟吃东西的对象
var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird) //创建一个麻雀吃东西的对象
//var c2:EatSomething[Sparrow] = new EatSomething[Sparrow](new Sparrow)
//问题:能否将c1 付给c2?
//原因:尽管Bird是Sparrow的父类,但是EatSomething[Bird]不是EatSomething[Sparrow]的父类
//接收参数:Bird 是Sparrow的父类
var c2:EatSomething[Sparrow] = c1
}
}

6、隐式转换函数:implicit

package main.scala.demo3
//隐式转换
//水果
class Fruit(name:String){
def getFruitName():String = {name}
} //猴子
class Monkey(f:Fruit){
def say() = {println("Monkey like" + f.getFruitName())}
} object ImplicitDemo { //定义一个隐式转换规则:Fruit对象 ===》Monkey对象
implicit def fruit2Monkey(f:Fruit):Monkey = {new Monkey(f)} def main(args: Array[String]) {
//创建一个水果的对象
var f:Fruit = new Fruit("香蕉") //希望直接调用f.say()方法
//将Fruit的对象转换成Monkey的对象
f.say()
}
}

运行:

Monkey like香蕉

7、隐式参数:参数前面加一个implicit关键字

//Scalad的隐式参数
def testParam(implicit name:String) = {println("The value is "+name)}
implicit val name:String = "这是一个隐式参数" //调用:不想传递参数
testParam //找到两个值中小的那个
def smaller[T](a:T,b:T)(implicit order:T => Ordered[T]) = if(a<b)
a else b
smaller(1,3)
smaller("Hello","abc")

运行结果:

testParam: testParam[](implicit val name: String) => Unit
name: String = 这是一个隐式参数 The value is 这是一个隐式参数
res0: Unit = () smaller: smaller[T](val a: T,val b: T)(implicit val order: T => Ordered[T]) => T res1: Int = 1
res2: String = Hello

8、隐式类:类前面加一个implicit关键字

package main.scala.demo4

/*
隐式类的功能:对类的功能进行加强
顺序:
第一步:先调用隐式转换类,把 1 ===> Calc对象
第二步:调用Calc对象的add方法
*/
object ImplicitDemo4 { //定义一个隐式类
implicit class Calc(x:Int){
def add(y:Int) = x + y
} def main(args: Array[String]): Unit = {
//进行两个数的相加 1.add(2)
println("两个数字的和是:" + 1.add(2))
}
}

运行:

两个数字的和是:3 

大数据笔记(二十六)——Scala语言的高级特性的更多相关文章

  1. 大数据笔记(十六)——Hive的客户端及自定义函数

    一.Hive的Java客户端 JDBC工具类:JDBCUtils.java package demo.jdbc; import java.sql.DriverManager; import java. ...

  2. python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码

    python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...

  3. 大数据spark学习第一周Scala语言基础

    Scala简单介绍 Scala(Scala Language的简称)语言是一种能够执行于JVM和.Net平台之上的通用编程语言.既可用于大规模应用程序开发,也可用于脚本编程,它由由Martin Ode ...

  4. Java基础学习笔记二十六 JDBC

    什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库,J ...

  5. 大数据笔记(十二)——使用MRUnit进行单元测试

    package demo.wc; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.io.IntW ...

  6. 大数据笔记(十)——Shuffle与MapReduce编程案例(A)

    一.什么是Shuffle yarn-site.xml文件配置的时候有这个参数:yarn.nodemanage.aux-services:mapreduce_shuffle 因为mapreduce程序运 ...

  7. Java笔记(二十六)……IO流上 字节流与字符流

    概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...

  8. 大数据笔记(十八)——Pig的自定义函数

    Pig的自定义函数有三种: 1.自定义过滤函数:相当于where条件 2.自定义运算函数: 3.自定义加载函数:使用load语句加载数据,生成一个bag 默认:一行解析成一个Tuple 需要MR的ja ...

  9. 大数据笔记(十五)——Hive的体系结构与安装配置、数据模型

    一.常见的数据分析引擎 Hive:Hive是一个翻译器,一个基于Hadoop之上的数据仓库,把SQL语句翻译成一个  MapReduce程序.可以看成是Hive到MapReduce的映射器. Hive ...

随机推荐

  1. awk对文件的奇偶行做处理

    { if(NR % 2 == 0) printf("%s\n", $0) else printf("%s, ", $1) } awk -f awk.awk da ...

  2. python3 修改大数据量excel内容

    最好使用python3 64位 对excel的修改操作: from openpyxl import load_workbook import time #打开一个excel表格.xlsx wb = l ...

  3. PyQt5_主要的类库

    1.PyQt5包括的主要模块如下. QtCore模块——涵盖了包的核心的非GUI功能,此模块被用于处理程序中涉及的时间.文件.目录.数据类型.文本流.链接.QMimeData.线程或进程等对象. Qt ...

  4. npm学习(六)之如何创建 Node.js 模块

    如何创建 Node.js 模块 Node.js 模块是一种可以发布到 npm 的包.当你创建一个新模块时,创建 package.json 文件是第一步. 你可以使用 npm init 命令创建 pac ...

  5. 【转载】jquery版的网页倒计时效果

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. ERP和MES系统的区别和关系?

    1.ERP和MES的区别:ERP(Enterprise Resources Planning)是企业资源计划,它是在物料需求计划MRP(Material Requirement Planning)和制 ...

  7. 初探 -5 JavaScript 语法

    JavaScript 是一个程序语言.语法规则定义了语言结构. JavaScript 语法 JavaScript 是一个脚本语言. 它是一个轻量级,但功能强大的编程语言. JavaScript 字面量 ...

  8. python 单引号、双引号和三引号混用

    单引号: 当单引号中存在单引号时,内部的单引号需要使用转义字符,要不然就会报错: 当单引号中存在双引号时,双引号可以不用加转义字符,默认双引号为普通的字符,反之亦然. 双引号: 当双引号中存在双引号时 ...

  9. oracle的sql 记录

    ----1.分组函数--select max(tfi.expected_scale) max1,min(tfi.expected_scale) min1,to_char(avg(tfi.expecte ...

  10. SpringBoot01——Framework Introduced and Helloworld

    1.介绍 SpringBoot主要解决的是在微服务的架构下简化配置(有快速配置).前后端分离.快速开发 优点: l 提供了快速启动入门 l 开箱即用.提供默认配置 l 内嵌容器化web项目 l 没有冗 ...