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. Mac上微信小程序官方开发工具卡死的问题

    Mac上微信小程序官方开发工具打开后卡死,无法操作,也关不掉,解决方案: 三步: 1.在应用中删除“微信web开发者工具” 2.删除一下几个配置和缓存文件: 1.-/Library/Applicati ...

  2. nginx配置样例

    简单的nginx配置如下,包含了静态文件配置.websocket.socket.io的配置: user nobody; worker_processes 3; #master_process off; ...

  3. 如鹏网学习笔记(八)CSS

    CSS 一.CSS简介 1,CSS (Cascading Style Sheets) 级联样式表 ,是一种计算机语言,用来控制HTML内容的显示效果 2,CSS预先定义了众多的和显示效果有关的样式属性 ...

  4. 三:SQL server基础

    /一:创建数据库/ use master if exists (select * from sysdatabases where name='数据库名称') drop database 数据库名称 - ...

  5. springboot+mybatis遇到BUG:自动注入失败

    今天用springboot+mybatis写一个小demo遇到如下错误 Error starting ApplicationContext. To display the conditions rep ...

  6. java:模拟栈操作

    import java.util.ArrayList; public class MyStack { private ArrayList<Object> arrayList; public ...

  7. 为什么要学习 UML?

    UML 的首要价值是沟通和理解.好的图形可以帮助沟通设计思想,尤其是要回避许多细节时,图形也可以帮助你理解软件系统或业务流程.作为团队的成员,尝试弄清楚某些东西时,图形有助于理解和沟通整个团队所理解到 ...

  8. 关键业务系统的JVM参数推荐(2018仲夏版) (强烈推荐 唯品会)

    年更贴,因为两年里遇到的事情,一些想法变了.也补充了不少VJTools的内容,比如为伸手党们准备的jvm-options.sh. 在关键的业务系统里,除了继续追求技术人员最爱的高吞吐与低延时之外,系统 ...

  9. 关于VUE中 import 、 export 和 export default 的注意问题

    1.import引入一个依赖包,不需要相对路径.import 引入一个自己写的js文件,是需要相对路径的. 示例:import axios from ‘axios’; import AppServic ...

  10. python中字符串格式化%与.format

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...