===================== 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. ZOJ 2836 Number Puzzle 题解

    题面 lcm(x,y)=xy/gcd(x,y) lcm(x1,x2,···,xn)=lcm(lcm(x1,x2,···,xn-1),xn) #include <bits/stdc++.h> ...

  2. HDU1846 Brave Game 题解

    题面 本题是一道有向图博弈问题: 该题便是著名的巴什博弈: 我们可以发现,当n=0的时候后手必胜(设其为P态),n=1~m这几种状态由于先手可以一次全部取完导致先手必胜(设其为N态). 接着当n=m+ ...

  3. 刷机,twrp,安装xposed

    首先明白几个名词: recovery模式,类似于pc端的PE系统,每个手机都有自带的rec,但不好用,最好自己刷一个,现在市面最好用的是twrp fastboot模式,比recovery更底层,进入f ...

  4. sys模块&json模块&pickle模块

    sys模块&json模块&pickle模块 sys模块 一.导入方式 import sys 二.作用 与Python解释器交互 三.模块功能 3.1 经常使用 sys.path #返回 ...

  5. kafka 教程(一)-初识kafka

    消息队列 MQ 消息队列就是 消息 message 加 队列 queue,是一种消息传输的容器,提供生产和消费 API 来存储和获取消息. 消息队列分两种:点对点(p2p).发布订阅(pub/sub) ...

  6. ElasticSearch实战系列四: ElasticSearch理论知识介绍

    前言 在前几篇关于ElasticSearch的文章中,简单的讲了下有关ElasticSearch的一些使用,这篇文章讲一下有关 ElasticSearch的一些理论知识以及自己的一些见解. 虽然本人是 ...

  7. es6 filter() 数组过滤方法总结(转载)

    1.创建一个数组,判断数组中是否存在某个值 var newarr = [ { num: 1, val: 'ceshi', flag: 'aa' }, { num: 2, val: 'ceshi2', ...

  8. 生成树计数及应用 Matrix-Tree

    例:给定一个图,图上每条边是红色或蓝色 求恰好有K条红边的生成树的个数,N<=50. Matrix-Tree定理 对于限制条件可以利用多项式,把红边边权设为X,蓝边边权设为1. 最后求行列式得到 ...

  9. BZOJ3745 / SP22343 NORMA2 - Norma 分治,CDQ分治

    要命的题目. 写法:分类讨论进行计算. 枚举过每一个\(mid\)的所有区间.对于左端点\(i∈[l, mid - 1]\),向左推并计算\([l,mid]\)范围内的最大\(/\)最小值. 然后右端 ...

  10. .NET界面控件DevExpress全新发布v19.1.4|更改DCT解码器

    DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...