谈谈scala 的模式匹配

在 java 中我倒是较少使用 switch case ,大部分都是if else 搞定
但是在 scala 中 模式匹配 可以说是登峰造极了,你可以用它完成之前很多繁琐机械的问题,最主要是灵活多变,总有一款适合你
先讲讲最简单的
我这里有一个需求
把 hdfs 上的原始日志数据进行压缩,其中压缩方式 有 snappy gzip lzo defalte 大致四种,原先我把每一种压缩方式都写了一个独立的方法,验证都可以正常使用,写代码要时刻有重构的想法,我一看大部分 流程都一致,可以把这些合四为一,把单独不一致的内容拿出来,做case 判断识别
比如
单个的 snappy 压缩

  /**
    * hdfs 文件  snappy 压缩
    *
    * @param fs
    * @param conf
    * @param inpath
    * @param outPath
    */
  def hdfsFileCompressBySnappyCodec(fs: FileSystem, conf: Configuration, inpath: String, outPath: String): Unit = {
    //压缩时 读取fsdata流  写入 compress流【fs-buff-compress]
    val inputPath: Path = new Path(inpath)
    val inFsData: FSDataInputStream = fs.open(inputPath)
    val snappyCC: SnappyCodec = new SnappyCodec()
    //val snappyComp:SnappyCompressor=new SnappyCompressor()
    snappyCC.setConf(conf)

    // val snappyFile :String= getFileOriginName(inpath) +snappyCC.getDefaultExtension
    val inSubPath: String = getOutFileSubPath(inpath)
    var nOutPath = ""
    if (outPath.endsWith("/")) {
      nOutPath = outPath.substring(0, outPath.length - 1)
    } else {
      nOutPath = outPath
    }
    val snappyFile: String = nOutPath + inSubPath + snappyCC.getDefaultExtension
    val outdir: Path = new Path(snappyFile)
    val fsDataOutStream: FSDataOutputStream = fs.create(outdir)
    val fsBufferOutStream: BufferedOutputStream = new BufferedOutputStream(fsDataOutStream)
    val compressOutStream: CompressionOutputStream = snappyCC.createOutputStream(fsBufferOutStream)
    val bufInpStream: BufferedInputStream = new BufferedInputStream(inFsData)
    val ioBuffer: Array[Byte] = new Array[Byte](64 * 1024)
    var readLen: Int = 0
    val start = System.currentTimeMillis()
    println("snappy codec begining  ||  " + snappyFile)
    try {
      while ( {
        readLen = bufInpStream.read(ioBuffer)
        readLen != -1
      }) {
        compressOutStream.write(ioBuffer, 0, readLen)
      }
    } catch {
      case e: Exception => e.printStackTrace()
    } finally {
      compressOutStream.flush()
      compressOutStream.finish()
      compressOutStream.close()
      IOUtils.closeStream(inFsData)
      IOUtils.closeStream(fsDataOutStream)
      //fs.close()
    }
    val end = System.currentTimeMillis()
    val timeCause = end - start
    println("snappy codec finish   ||  " + snappyFile + " || 时间消耗   " + timeCause + " ms")

  }


其实就是 不同压缩格式 创建不同的 codec
所以我做了 case就是创建不同codec ,通过 查询 发现 这些 codec
都 是 CompressionCodec的子类,
所以就这样办了
方法增加一个 输入的参数 string codecMethod作为制定 压缩格式

 val codec:CompressionCodec =codecMethod match {
      case "SNAPPY" => new SnappyCodec()
//     { codec.asInstanceOf[SnappyCodec].setConf(conf)
//      }
      case "GZIP" => new GzipCodec()
      case "LZO" => new Lz4Codec()
      case "DEFALTE" => new DefaultCodec()
      case _ => new DefaultCodec()
    }

这样一来 剩下的流程都一致,可以做一些 一致的处理

除了上边的,其实我还有另一种case的使用 就是在一个方法中 通过
case 调用不同的方法,
我前面讲过 我在最开始前分别写了 四个独立的压缩方法,这四个方法相当于压缩算子,只能对单独文件进行 压缩,可是我们 在hdfs上 往往都是 目录嵌套好几层,直接从最外层 开始压缩,一口气可能就是成千上万个文件了,所以我写了一个 目录压缩方法,来对目录嵌套下的文件进行压缩,并且我在 目录压缩方法中使用了 递归,简直 不能再好了
,当然在目录压缩方法中也是可以指定 压缩格式的,我在这里 是通过调用独立的压缩算子方法实现 的


 codec match {
          case "SNAPPY" => hdfsFileCompressBySnappyCodec(fs, conf, inpath, outPath)
          case "GZIP" => hdfsFileCompressByGzipCodec(fs, conf, inpath, outPath)
          case "LZO" => LZOCodecHdfsFileCompressBy(fs, conf, inpath, outPath)
          case "DEFALTE" =>deflateCompressForHdfsFile(fs,conf,inpath,outPath)
          case _ => deflateCompressForHdfsFile(fs,conf,inpath,outPath)
        }

具体的目录压缩方法

/**
    * 按目录对文件  进行 snappy  gzip  lzo  压缩
    * @param fs
    * @param conf
    * @param inpath 输入目录
    * @param outPath 输出目录
    * @param codec  压缩格式 缩写  SNAPPY  GZIP LZO  DEFALTE 默认为defalte
    * @param propertiesPath  压缩文件类型刷选 属性文件路径
    */
  def DirCompressBySnappyGzipLzoCodec(fs: FileSystem, conf: Configuration, inpath: String, outPath: String, codec: String="GZIP")(propertiesPath: String="/usr/local/info.properties"): Unit = {
    val inputPa: Path = new Path(inpath)
    val fsStatus: FileStatus = fs.getFileStatus(inputPa)
    var flag = false
    try{

    if (fsStatus.isFile) {
      flag = CompressUtils.boolFilePrefixContains(inpath, propertiesPath)
      if (flag) {
        codec match {
          case "SNAPPY" => hdfsFileCompressBySnappyCodec(fs, conf, inpath, outPath)
          case "GZIP" => hdfsFileCompressByGzipCodec(fs, conf, inpath, outPath)
          case "LZO" => LZOCodecHdfsFileCompressBy(fs, conf, inpath, outPath)
          case "DEFALTE" =>deflateCompressForHdfsFile(fs,conf,inpath,outPath)
          case _ => deflateCompressForHdfsFile(fs,conf,inpath,outPath)
        }
      }
    } else if (fsStatus.isDirectory) {
      val listFs: Array[FileStatus] = fs.listStatus(inputPa)
      listFs.foreach(fil => {
        val fsiN = fil.getPath.getName
        println("path dir name  " + fsiN)
        println("path parent  " + fil.getPath.getParent)
        val uriPath = fil.getPath.getParent.toString
        var newInp = ""
        if (uriPath.contains(":9000/")) {
          val uriIndex = uriPath.indexOf(":9000/")
          newInp = uriPath.substring(uriIndex + 5) + "/" + fsiN
        } else {
          newInp = uriPath + "/" + fsiN
        }
        if (fil.isFile) {
          flag = CompressUtils.boolFilePrefixContains(newInp, propertiesPath)
          if (flag) {
            codec match {
              case "SNAPPY" => hdfsFileCompressBySnappyCodec(fs, conf, newInp, outPath)
              case "GZIP" => hdfsFileCompressByGzipCodec(fs, conf, newInp, outPath)
              case "LZO" => LZOCodecHdfsFileCompressBy(fs, conf, newInp, outPath)
              case "DEFALTE" =>deflateCompressForHdfsFile(fs,conf,inpath,outPath)
              case _ => deflateCompressForHdfsFile(fs,conf,inpath,outPath)
            }
          }
        } else {
          DirCompressBySnappyGzipLzoCodec(fs, conf, newInp, outPath, codec)(propertiesPath)
        }
      })
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容