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 ...
随机推荐
- C# 中的隐式类型转换(运算时的隐式转换)和显示类型转换
区别: 隐式转换失败编译会报错. 显示转换有可能精度丢失. 根据项目的编译设置,显示转换溢出可能会报错,如果设置溢出且未使用checked检查,运行时如果发生溢出会产出未知的计算结果. 在数字运算时, ...
- JAVA获取5位随机数
package baofoo.utils; import org.junit.Test; import java.text.SimpleDateFormat; import java.util.Dat ...
- 撩课-Java每天5道面试题第20天
131.Spring是什么? 他解决的是业务逻辑层和其他各层的松耦合问题, 因此它将面向接口的编程思想 贯穿整个系统应用. Spring是一个轻量级的IoC和AOP容器框架. 目的是解决企业应用开发的 ...
- 基于netcore对ElasitSearch客户端NEST查询功能的简单封装NEST.Repository
NEST.Repository A simple encapsulation with NEST client for search data form elasticsearch. github A ...
- hihernate一对多关联映射
hihernate一对多关联映射 一对多关联映射利用了多对一关联映射原理 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一 一对多关联映射:在多的一端加入一个外键指向一的一端 ...
- C++ Knowledge series 1
Programming language evolves always along with Compiler's evolvement. 1. The C++ Object Model: Strou ...
- 空间分析开源库GEOS
History of GEOS GEOS中Geometry的结构 GEOS分析功能简介 1.History of GEOS JTS Topology Suite是Ma ...
- java 策略模式
<Head First 设计模式>学习中 设计原则 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起 针对接口编程,而不是针对实现编程 多用组合少用继承 ...
- TCP协议 状态解析和状态统计
一.三次握手和四次挥手 1.建立连接(三次握手) (1)服务器会处于listen状态,客户端发送一个带SYN标志的TCP报文到服务器. (2)服务器端回应客户端的请求,这是三次握手中的第2个报 ...
- C#-MDI-多窗口通信方法总结
总结C#中窗体间传递数据的几种方法 (由别人的方法整理) 转自:http://blog.csdn.net/daisy423xu/article/details/1579854 在编写C#windows ...