zoukankan      html  css  js  c++  java
  • 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 + "
    ")
        bw.close()
        fw.close()
      }
    }
    
    
    
    
    
  • 相关阅读:
    Android开发学习之路-使用Handler和Message更新UI
    Android开发学习之路-Service和Activity的通信
    Android开发学习之路-自定义ListView(继承BaseAdapter)
    URI、URL、URN
    理解 node.js 的事件循环
    创建hexo风格的markdown页面
    heroku
    js通过沿着作用域链还是原型链查找变量
    浏览器中实现3D全景浏览
    数据可视化图表ECharts
  • 原文地址:https://www.cnblogs.com/leihuazhe/p/8043183.html
Copyright © 2011-2022 走看看