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 经典的模式匹配和尾递归的更多相关文章

  1. 第74讲:从Spark源码的角度思考Scala中的模式匹配

    今天跟随王老师学习了从源码角度去分析scala中的模式匹配的功能.让我们看看源码中的这一段模式匹配: 从代码中我们可以看到,case RegisterWorker(id,workerHost,.... ...

  2. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  3. Scala基础:模式匹配和样例类

    模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...

  4. scala里的模式匹配和Case Class

    模式匹配的简介 scala语言里的模式匹配可以看作是java语言中switch语句的改进. 模式匹配的类型 包括:常量模式.变量模式.构造器模式.序列模式.元组模式以及变量绑定模式等. 常量模式匹配 ...

  5. Scala面向对象和模式匹配

    我们要封装数据,定义模板等操作,所以我们需要面向对象. 一.scala中的单例对象 在scala当中,是没有static的,scala给我们提供了单例模式的实现方法.就是使用关键字object. st ...

  6. scala中的模式匹配

    基本语法 变量 match { case 值1 => 代码 case 值2 => 代码 ... case 值N if (...) => 代码 case _ => 代码 } 常量 ...

  7. [Scala] Pattern Matching(模式匹配)

    Scala中的match, 比起以往使用的switch-case有著更強大的功能, 1. 傳統方法 def toYesOrNo(choice: Int): String = choice match ...

  8. scala 学习笔记--模式匹配

    1.switch java代码 switch (cause) { case ‘2‘ : dropTime=time; case ‘8’:case ‘9’ : case ‘10’:case ‘11’ : ...

  9. 第3节 Scala中的模式匹配:1 - 5

    7.    模式匹配和样例类 Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句.类型检查等.并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配. 7.1 ...

随机推荐

  1. 使用PowerShell为SSAS Role添加Membership

    PowerShell, SSAS, Role, Membership 上篇随笔使用PowerShell创建SSAS Role贴出了如何使用PowerShell批量创建Role,由于个人项目需求,创建R ...

  2. C# 泛型使用笔记

    泛型的基本概念我就不在这重复了,不了解的同学请自行百度. 我主要写下我在项目中要到的泛型实例.献丑了.....有什么不好或不对的地方大家尽可评论留言. 为什么要用泛型? 通过使用泛型,我们可以极大地提 ...

  3. ETL第一篇(Kettle Spoon) 初遇

    ETL第一篇(Kettle Spoon) 初遇 ETL第二篇 调用webservice 简介 Kettle 是一款国外开源的 ETL 工具,纯 Java 编写,绿色无需安装,数据抽取高效稳定(数据迁移 ...

  4. Linux下一个最简单的不依赖第三库的的C程序(2)

    一个最简单的C程序,如下: main.c: int main() { char *str = "Hello World"; ; } 在64位平台上编译一个32位的程序,如下:(32 ...

  5. Springboot @ResponseBody返回中文乱码

    最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...

  6. spring-cloud-sleuth简单使用

    快速开始 一.导入依赖 <!--链路追踪 start--> <dependency> <groupId>org.springframework.cloud</ ...

  7. eclipse的debug技巧之一

    如下图,断点设置的地方会在i==0时就停住,假如我们想在i等于某个值的时候才停住,那么可以添加“过滤条件” 具体操作是在debug模式下,右键breakpoints标签下我们所设置的断点,点击右键菜单 ...

  8. MongoDB客户端及监控工具

    现在许多应用都使用MongoDB存储大量的业务数据,MongoDB基于文档式的存储,在大数据行业的应用还是很普遍的.MongoDB的客户端工具也很多,基于web的却不多,国产的就更少了,下面这款国产的 ...

  9. Class.forName("com.mysql.jdbc.Driver")找不到类

    解决方法: 如果是java项目,只需要引入mysql-connector-java-8.0.13.jar就可以运行java项目. 建的如果是web工程,需要把mysql-connector-java- ...

  10. bitset(01串)优化

    bitset的经典使用: 见代码及注释: #include<bitset> #include<algorithm> using namespace std; //只需调用< ...