Scala 经典的模式匹配和尾递归
Scala 经典的模式匹配和尾递归
package io
import java.io.{BufferedWriter, File, FileWriter}
import java.text.SimpleDateFormat
import scala.annotation.tailrec
import scala.io.Source
/**
* author: HuaZhe Ray
*
* describe: 计算服务调用平均时长
*
* createDate: 2017/12/15
* createTime: 10:57
*
*/
object AverageService {
type TIME = String
type THREAD = String
type SERVICE = String
type WAYS = String
type METHOD = String
val sdf = new SimpleDateFormat("MM-dd hh:mm:ss SSS")
val regex = """(\d{2}-\d{2} \d{2}:\d{2}:\d{2} \d{3}) ([^\s]+) DEBUG ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) (.+)""".r
def main(args: Array[String]): Unit = {
// 服务调用次数
countByServiceName
Thread.sleep(1000)
// 服务调用时长
analyzeAverageTime
}
/**
* 最新优化,求服务调用次数 根据 带有request单词的作为一次服务,并过滤掉 INFO 日志, 取 DEBUG 日志
* 2017-12-14 14:50
*/
def countByServiceName(): Unit = {
val source = Source.fromFile("E:\\scala\\detail-test.log", "UTF-8")
val lists:List[(String,String,String,String,String)] = source.getLines().collect{
case regex(timestamp, thread,c,service,version,method,requests) => (timestamp,thread,service,method,requests)
}.toList
val requests:List[(String,String,String)] = lists.filter(_._5.contains("request")).map (line =>{
(line._1,line._2,line._3+"."+line._4)
})
val countByServiceName:Map[String,Int] = requests.map((_, 1)).groupBy(_._1._3).map(t=>(t._1,t._2.size))
countByServiceName.foreach {
case (service, count) => println(s"$service count:$count")
}
}
/**
* 2017-12-15 统计服务调用平均时长
*
* 思路,根据正则 截取到 request 和 response 的 服务 ,然后根据时间排序 ---> 每次调用的 response - request 得到 服务调用时长
*/
def analyzeAverageTime(): Unit = {
val source = Source.fromFile("E:\\scala\\detail-test.log", "UTF-8")
val lists:List[(TIME,THREAD,SERVICE,METHOD,WAYS)] = source.getLines().collect{
case regex(timestamp, thread,c,service,version,method,requests) => (timestamp,thread,service,method,requests)
}.toList
val requests:List[(TIME,THREAD,SERVICE,WAYS)] = lists.filter(_._5.contains("request")).map (line =>{
(line._1,line._2,line._3+"."+line._4,"request")
})
val response:List[(TIME,THREAD,SERVICE,WAYS)] = lists.filter(_._5.contains("response")).map (line =>{
(line._1,line._2,line._3+"."+line._4,"response")
})
// 得到所有 request 和 response 结果
val totalServices = (requests ++ response).sortWith((t1,t2) => t1._1 < t2._1).take(10)
//具体进行处理
processByTailRec(totalServices,Map[(THREAD,SERVICE),TIME]())
}
/**
* 通过定义 mutable Map 来 存放 foreach 临时变量, 进行相减操作
* @param array
*/
def process(array:List[(TIME,THREAD,SERVICE,WAYS)]): Unit = {
val pendings = collection.mutable.Map[(THREAD,SERVICE),TIME]()
array.foreach{
case (time,thread,service,ways) => if(ways=="request") {
pendings += (thread,service) -> time
}
else {
pendings.get((thread,service)) match {
case Some(time0) => val msg = s"Thread: ${thread} Service: ${service} average-time: ${BigDecimal(sdf.parse(time).getTime - sdf.parse(time0).getTime)} ms"
pendings.remove((thread, service))
writeLogToFile(msg) ; println(msg)
case None => println("nothing")
}
}
}
}
/**
* 使用尾递归的方法,消除 var 和 mutable Map
* @param array
* @param pendings
*/
@tailrec
def processByTailRec(array:List[(TIME,THREAD,SERVICE,WAYS)],pendings:Map[(THREAD,SERVICE),TIME]): Unit ={
array match {
case (time,thread,service,"response") :: tail =>
pendings.get((thread, service)) match {
case Some(time0) =>
val msg = s"Thread: ${thread} Service: ${service} average-time: ${BigDecimal(sdf.parse(time).getTime - sdf.parse(time0).getTime)} ms"
writeLogToFile(msg) ; println(msg)
processByTailRec(tail, pendings - ((thread, service)))
case None =>
processByTailRec(tail, pendings)
}
case (time, thread, service, "request") :: tail =>
processByTailRec(tail, pendings + ((thread, service) -> time) )
case Nil => None
}
}
/**
* 写文件
* @param args
*/
def writeLogToFile(args:String): Unit ={
val fw = new FileWriter(new File("E:\\scala\\service_average.log"),true)
//写入中文字符时会出现乱码
val bw = new BufferedWriter(fw)
bw.write(args + "\r\n")
bw.close()
fw.close()
}
}
Scala 经典的模式匹配和尾递归的更多相关文章
- 第74讲:从Spark源码的角度思考Scala中的模式匹配
今天跟随王老师学习了从源码角度去分析scala中的模式匹配的功能.让我们看看源码中的这一段模式匹配: 从代码中我们可以看到,case RegisterWorker(id,workerHost,.... ...
- (数据科学学习手札49)Scala中的模式匹配
一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...
- Scala基础:模式匹配和样例类
模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...
- scala里的模式匹配和Case Class
模式匹配的简介 scala语言里的模式匹配可以看作是java语言中switch语句的改进. 模式匹配的类型 包括:常量模式.变量模式.构造器模式.序列模式.元组模式以及变量绑定模式等. 常量模式匹配 ...
- Scala面向对象和模式匹配
我们要封装数据,定义模板等操作,所以我们需要面向对象. 一.scala中的单例对象 在scala当中,是没有static的,scala给我们提供了单例模式的实现方法.就是使用关键字object. st ...
- scala中的模式匹配
基本语法 变量 match { case 值1 => 代码 case 值2 => 代码 ... case 值N if (...) => 代码 case _ => 代码 } 常量 ...
- [Scala] Pattern Matching(模式匹配)
Scala中的match, 比起以往使用的switch-case有著更強大的功能, 1. 傳統方法 def toYesOrNo(choice: Int): String = choice match ...
- scala 学习笔记--模式匹配
1.switch java代码 switch (cause) { case ‘2‘ : dropTime=time; case ‘8’:case ‘9’ : case ‘10’:case ‘11’ : ...
- 第3节 Scala中的模式匹配:1 - 5
7. 模式匹配和样例类 Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句.类型检查等.并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配. 7.1 ...
随机推荐
- 使用PowerShell为SSAS Role添加Membership
PowerShell, SSAS, Role, Membership 上篇随笔使用PowerShell创建SSAS Role贴出了如何使用PowerShell批量创建Role,由于个人项目需求,创建R ...
- C# 泛型使用笔记
泛型的基本概念我就不在这重复了,不了解的同学请自行百度. 我主要写下我在项目中要到的泛型实例.献丑了.....有什么不好或不对的地方大家尽可评论留言. 为什么要用泛型? 通过使用泛型,我们可以极大地提 ...
- ETL第一篇(Kettle Spoon) 初遇
ETL第一篇(Kettle Spoon) 初遇 ETL第二篇 调用webservice 简介 Kettle 是一款国外开源的 ETL 工具,纯 Java 编写,绿色无需安装,数据抽取高效稳定(数据迁移 ...
- Linux下一个最简单的不依赖第三库的的C程序(2)
一个最简单的C程序,如下: main.c: int main() { char *str = "Hello World"; ; } 在64位平台上编译一个32位的程序,如下:(32 ...
- Springboot @ResponseBody返回中文乱码
最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...
- spring-cloud-sleuth简单使用
快速开始 一.导入依赖 <!--链路追踪 start--> <dependency> <groupId>org.springframework.cloud</ ...
- eclipse的debug技巧之一
如下图,断点设置的地方会在i==0时就停住,假如我们想在i等于某个值的时候才停住,那么可以添加“过滤条件” 具体操作是在debug模式下,右键breakpoints标签下我们所设置的断点,点击右键菜单 ...
- MongoDB客户端及监控工具
现在许多应用都使用MongoDB存储大量的业务数据,MongoDB基于文档式的存储,在大数据行业的应用还是很普遍的.MongoDB的客户端工具也很多,基于web的却不多,国产的就更少了,下面这款国产的 ...
- Class.forName("com.mysql.jdbc.Driver")找不到类
解决方法: 如果是java项目,只需要引入mysql-connector-java-8.0.13.jar就可以运行java项目. 建的如果是web工程,需要把mysql-connector-java- ...
- bitset(01串)优化
bitset的经典使用: 见代码及注释: #include<bitset> #include<algorithm> using namespace std; //只需调用< ...