scala,实现case class类的时候 业务字段过多导致的异常。不能超过22个字段

一、背景

1、在scala-2.10.x版本种,case class的元素超过22个以后即会编译报错

2、有些业务场景下,需要超过22个元素的值

 

我们项目当中日志一共有105个字段,在对原始日志进行处理转换成parquet文件的过程中,我们使用的方法是定义一个case class类,将这105个字段封装到这个对象里面,基于这种方式构建的DataFrame。结果运行的时候报错了,之后我们查阅官网,发现在scala 2.10版本中case class一共只支持22个字段,如果超过了就会报错,然后官网也给了我们解决方法,就是自定义一个类实现product特质,这样就能解决这个问题

二、如何解决

1、Scala提供了解决方案,即使用类实现Product特质

package com.ngaa.scala /**
  * @author Created by yangjf on 20180712.
  *         Update date:
  *         Time: 15:43
  *         Project: dev-spark01-examples
  *         Package: com.ngaa.scala
  *         Describe :   Scala构建超过22个元素的class
  *    API参考:
  *  https://www.scala-lang.org/api/current/scala/Product.html
  *  学习参考:
  *    https://www.artima.com/pins1ed/
  *
  */
object More22Elements { def main(args: Array[String]) { val student = new Student(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27) /* 获取其中一个元素 */
    println(student.productElement(1).toString) /* 是否包含元素:23 */
    println(student.canEqual(23)) /* 遍历元素 */
    student.productIterator.foreach(println) /* toString方法 */
    println(student.productPrefix) println(student.equals(student)) } } /** Student类中有大于22个元素的实现  */
class Student(one: Int, two: Int, three: Int, four: Int, five: Int
              , six: Int, seven: Int, eight: Int, nine: Int, ten: Int, eleven: Int, twelve: Int
              , thirteen: Int, fourteen: Int, fifteen: Int, sixteen: Int
              , seventeen: Int, eighteen: Int, nineteen: Int, twenty: Int, first: Int, second: Int
              ,third:Int, fourth: Int, fifth: Int, sixth: Int, seventh: Int) extends Product { val arrays = Array(one, two, three, four, five , six, seven, eight, nine, ten, eleven, twelve , thirteen, fourteen, fifteen, sixteen , seventeen, eighteen, nineteen, twenty, first, second, third , fourth, fifth, sixth, seventh) /**
    * 
    * 自定义比较:是否包含这个元素
    *
    * @param that 输入的元素
    * @return 是否包含,true代表包含
    */
  override def canEqual(that: Any): Boolean = arrays.contains(that) /**
    * 
    * 获取迭代器
    *
    * @return 迭代
    */
  override def productIterator: Iterator[Int] = new scala.collection.Iterator[Int] { private var c: Int = 0
    private val cMax = productArity def hasNext = c < cMax

    def next() = { val result = productElement(c) c += 1
      result } } 
/**
    * 
    * 根据下标获取元素
    *
    * @param n 下标
    * @return 元素
    */
  override def productElement(n: Int): Int = arrays(n) 
/**
    * 
    * 元素个数
    *
    * @return 元素个数
    */
  override def productArity: Int = arrays.length 
/**
    * 
    * 类似toString方法
    *
    * @return 元素链接字符串
    */
  override def productPrefix = arrays.mkString("\t") 
}

2、升级scala版本,2.11版本之后是直接可以用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章