大数据技术之_16_Scala学习_12
经典的 WordCount 的讲解
示例代码如下:
package com.atguigu.chapter14.homework.wordcount
/*
val lines = List("atguigu han hello ", "atguigu han aaa aaa aaa ccc ddd uuu")
使用映射集合,list中,各个单词出现的次数,并按出现次数排序。
*/
object WordCount {
def main(args: Array[String]): Unit = {
val lines = List("atguigu han hello ", "atguigu han aaa aaa aaa ccc ddd uuu")
// 先分步完成,再组合
// 1、扁平:将集合中的每个元素的子元素映射到某个函数并返回新的集合。
// val res1: List[String] = lines.flatMap((s: String) => s.split(" ")) // 简写形式如下
// val res1: List[String] = lines.flatMap(s => s.split(" "))
val res1: List[String] = lines.flatMap(_.split(" "))
println("res1=" + res1) // res1=List(atguigu, han, hello, atguigu, han, aaa, aaa, aaa, ccc, ddd, uuu)
// 2、做成对偶 List,才能分组并统计
// val res2 = res1.map((s:String) => (s, 1)) // 简写形式如下
// val res2 = res1.map(s => (s, 1))
val res2 = res1.map((_, 1))
println("res2=" + res2) // res2=List((atguigu,1), (han,1), (hello,1), (atguigu,1), (han,1), (aaa,1), (aaa,1), (aaa,1), (ccc,1), (ddd,1), (uuu,1))
// 3、分组。把不同的单词归属到不同的组
// val res3 = res2.groupBy((x:(String, Int)) => x._1) // 简写形式如下
// val res3 = res2.groupBy(x => x._1)
val res3 = res2.groupBy((_._1))
println("res3=" + res3) // res3=Map(han -> List((han,1), (han,1)), ddd -> List((ddd,1)), ..., aaa -> List((aaa,1), (aaa,1), (aaa,1)))
// 4、对上面的各个元祖进行统计
// val res4 = res3.map((x:(String, List[(String, Int)])) => (x._1, x._2.size)) // 简写形式如下
val res4 = res3.map(x => (x._1, x._2.size))
println("res4=" + res4) // res4=Map(han -> 2, ddd -> 1, ccc -> 1, uuu -> 1, atguigu -> 2, hello -> 1, aaa -> 3)
// 5、排序,使用方法
// val res5 = res4.toList.sortBy((x:(String,Int)) => x._2) // 简写形式如下
// val res5 = res4.toList.sortBy(x => x._2)
val res5 = res4.toList.sortBy(_._2) // 从小到大
// val res5 = res4.toList.sortBy(_._2).reverse
println("rest5=" + res5) // rest5=List((ddd,1), (ccc,1), (uuu,1), (hello,1), (han,2), (atguigu,2), (aaa,3))
// 合并
println("rest0=" + lines.flatMap(_.split(" ")).map((_, 1)).groupBy((_._1)).map(x => (x._1, x._2.size)).toList.sortBy(_._2))
}
}
输出结果如下:
res1=List(atguigu, han, hello, atguigu, han, aaa, aaa, aaa, ccc, ddd, uuu)
res2=List((atguigu,1), (han,1), (hello,1), (atguigu,1), (han,1), (aaa,1), (aaa,1), (aaa,1), (ccc,1), (ddd,1), (uuu,1))
res3=Map(han -> List((han,1), (han,1)), ddd -> List((ddd,1)), ccc -> List((ccc,1)), uuu -> List((uuu,1)), atguigu -> List((atguigu,1), (atguigu,1)), hello -> List((hello,1)), aaa -> List((aaa,1), (aaa,1), (aaa,1)))
res4=Map(han -> 2, ddd -> 1, ccc -> 1, uuu -> 1, atguigu -> 2, hello -> 1, aaa -> 3)
rest5=List((ddd,1), (ccc,1), (uuu,1), (hello,1), (han,2), (atguigu,2), (aaa,3))
rest0=List((ddd,1), (ccc,1), (uuu,1), (hello,1), (han,2), (atguigu,2), (aaa,3))
第十七章 设计模式
17.1 学习设计模式的必要性
17.2 掌握设计模式的层次
独孤求败五个境界对应人生五个时期,看看你在什么境界?
第一境界:利剑,“凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋。”
第二境界:软剑,“紫薇软剑,三十岁前所用,误伤义士不祥,乃弃之深谷。”
第三境界:重剑,“重剑无锋,大巧不工。四十岁前恃之横行天下。”
第四境界:木剑,“四十岁后,不滞于物,草木竹石均可为剑。”
第五境界:无剑,“自此精修,渐进于无剑胜有剑之境。”
17.3 设计模式的介绍
17.4 设计模式的类型
17.5 简单工厂模式(生产类)
17.5.1 基本介绍
17.5.2 看一个具体的需求
17.5.3 使用传统的方式来完成
代码结构:
示例代码:
传统的方式的优缺点:
17.5.4 使用简单工厂模式来完成
简单工厂模式的设计方案: 定义一个实例化 Pizaa 对象的类,封装创建对象的代码。
示例代码如下:
SimplePizzaFactory.scala
package com.atguigu.chapter17.designpattern.simplefactory.pizzastore.user
import com.atguigu.chapter17.designpattern.simplefactory.pizzastore.pizza.{
CheesePizza, GreekPizza, PepperPizza, Pizza}
object SimplePizzaFactory {
// 提供一个创建 Pizza 的方法
def createPizza(t: String): Pizza = {
var pizza: Pizza = null
if (t.equals("greek")) {
pizza = new GreekPizza
} else if (t.equals("pepper")) {
pizza = new PepperPizza
} else if (t.equals("cheese")) {
pizza = new CheesePizza
}
return pizza
}
}
OrderPizza.scala 代码修改如下:
package com.atguigu.chapter17.designpattern.simplefactory.pizzastore.user
import com.atguigu.chapter17.designpattern.simplefactory.pizzastore.pizza.{
Pizza}
import scala.util.control.Breaks._
import scala.io.StdIn
class OrderPizza {
var orderType: String = _
var pizza: Pizza = _
breakable {
do {
println("请输入pizza的类型(使用简单工厂模式):")
orderType = StdIn.readLine()
pizza = SimplePizzaFactory.createPizza(orderType)
if (pizza == null) {
break()
}
this.pizza.prepare()
this.pizza.bake()
this.pizza.cut()
this.pizza.box()
}
while (true)
}
}
17.6 工厂方法模式(生产方法)
17.6.1 看一个新的需求
17.6.2 工厂方法模式介绍
17.6.3 工厂方法模式应用案例
图解1
图解2
17.7 抽象工厂模式(生产类)
17.7.1 基本介绍
17.7.3 抽象工厂模式应用案例
图解1
图解2
17.8 工厂模式小结
图解
将工厂抽象成两层:AbsFactory(抽象工厂) 和 具体实现的工厂子类。
17.9 单例模式
17.9.1 什么是单例模式+单例模式的应用场景
17.9.2 单例模式的应用案例-懒汉式
Scala 中没有静态的概念,所以为了实现 Java 中单例模式的功能,可以直接采用类对象(即伴生对象)方式构建单例对象。
示例代码如下:
package com.atguigu.chapter17.designpattern.singleton
object TestSingleTon1 extends App {
val singleTon1 = SingleTon1.getInstance
val singleTon2 = SingleTon1.getInstance
println(singleTon1.hashCode() + " " + singleTon2.hashCode())
}
// 将 SingleTon1 的构造方法私有化
class SingleTon1 private() {
println("~")
}
object SingleTon1 {
private var s: SingleTon1 = null
def getInstance = {
if (s == null) {
s = new SingleTon1
}
s
}
}
/* 底层代码
public SingleTon1 getInstance() {
if (s() == null) {
s_$eq(new SingleTon1());
}
return s();
}
*/
输出结果如下:
~
1626877848 1626877848
17.9.2 单例模式的应用案例-饿汉式
示例代码如下:
package com.atguigu.chapter17.designpattern.singleton
object TestSingleTon2 extends App {
val singleTon1 = SingleTon2.getInstance
val singleTon2 = SingleTon2.getInstance
println(singleTon1.hashCode() + " " + singleTon2.hashCode())
}
// 将 SingleTon2 的构造方法私有化
class SingleTon2 private() {
println("~~")
}
object SingleTon2 {
private val s: SingleTon2 = new SingleTon2
def getInstance = {
s
}
}
/* 底层代码
public SingleTon2 getInstance() {
return s();
}
*/
输出结果如下:
~~
1626877848 1626877848
17.10 装饰者模式(Decorator)
17.10.1 看一个具体的需求
17.10.2 方案1-较差的方案+小结和分析
方案1-较差的方案
方案1-小结和分析
17.10.3 方案2-好点的方案+小结和分析
方案2-好点的方案
方案2-小结和分析
17.10.4 装饰者模式原理
17.10.5 装饰者模式定义
17.10.6 用装饰者模式设计重新设计的方案
装饰者模式下的订单:2 份巧克力 + 1份牛奶的 LongBlack
17.10.7 装饰者模式咖啡订单项目应用实例
咖啡订单项目包结构
17.10.8 Java 中装饰者模式的经典使用
17.11 观察者模式(Observer)
17.11.1 看一个具体的需求
WeatherData 类
17.11.2 气象站设计方案1-普通方案
代码结构
代码实现
WeatherData.scala
package com.atguigu.chapter17.designpattern.observer.localinternetobserver
// 这个类是气象局维护的一个提供天气情况数据的核心类
class WeatherData {
private var mTemperatrue: Float = _ // 温度
private var mPressure: Float = _ // 气压
private var mHumidity: Float = _ // 湿度
private var mCurrentConditions: CurrentConditions = _ // 气象局的天气公告板(相当于显示界面,我们使用一个类进行模拟)
// 构造 WeatherData 对象时,将 CurrentConditions 传入进来
def this(mCurrentConditions: CurrentConditions) {
this
this.mCurrentConditions = mCurrentConditions
}
def getTemperature() = {
mTemperatrue
}
def getPressure() = {
mPressure
}
def getHumidity() = {
mHumidity
}
def dataChange() = {
// 更新天气公告板最新数据
mCurrentConditions.update(getTemperature(), getPressure(), getHumidity())
}
// 气象局更新天气情况的方法(先更新自己的核心类)
def setData(mTemperature: Float, mPressure: Float, mHumidity: Float) = {
this.mTemperatrue = mTemperature
this.mPressure = mPressure
this.mHumidity = mHumidity
dataChange() // 再去修改天气公告板最新数据
}
}
CurrentConditions.scala
package com.atguigu.chapter17.designpattern.observer.localinternetobserver
// 气象局的天气公告板
class CurrentConditions {
private var mTemperature: Float = _
private var mPressure: Float = _
private var mHumidity: Float = _
// 更新气象局的天气公告板最新数据,然后进行显示
def update(mTemperature: Float, mPressure: Float, mHumidity: Float) = {
this.mTemperature = mTemperature
this.mPressure = mPressure
this.mHumidity = mHumidity
display() // 显示操作
}
// 显示方法
def display() = {
println("***气象局的天气公告板显示 Today mTemperature: " + mTemperature + "***")
println("***气象局的天气公告板显示 Today mPressure: " + mPressure + "***")
println("***气象局的天气公告板显示 Today mHumidity: " + mHumidity + "***")
}
}
InternetWeather.scala
package com.atguigu.chapter17.designpattern.observer.localinternetobserver
object InternetWeather {
def main(