将StructField添加到现有模式

时间:2017-07-04 06:59:35

标签: scala loops apache-spark apache-spark-sql

我创建了一个类"属性"。每个类对象都有一个名称,一个数据类型和一个布尔值(可以为空或无)。所有对象都保存到ListBuffer中。

我尝试从列表中创建一个模式,并将每个值传递给StructField()。启动工作但遗憾的是,没有其他项目被添加到架构中。

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = {
  // Get first list item and initiate schema
  var schema = StructType(StructField(attr_list(0).name, attr_list(0).data_type, attr_list(0).nullable) :: Nil)

  // Add remaining items
  for (i <- 1 until attr_list.length) {
    schema.add(attr_list(i).name, attr_list(i).data_type, attr_list(i).nullable)
    println("Test " + attr_list(i).name.toString())
  }        
  return schema
}

2 个答案:

答案 0 :(得分:5)

add方法不会修改schema。认为它有点像Java中的字符串连接方法。

只需将添加结果重新分配给schema本身,就可以使代码按照您的意愿运行:

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = {

  // Get first list item and initiate schema
  var schema = StructType(StructField(attr_list(0).name, attr_list(0).data_type, attr_list(0).nullable) :: Nil)

  // Add remaining items
  for (i <- 1 until attr_list.length) {
    schema = schema.add(attr_list(i).name, attr_list(i).data_type, _list(i).nullable) // here
    println("Test " + attr_list(i).name.toString())
  }        
  return schema

}

另一个解决方案,可能更简单,就是只处理ListBuffer中的项目,从每个属性中生成StructField,并将结果直接传递给StructType构造函数(接受ListBuffer的父类Seq作为参数)。

def attributeToStructField(attr: Attribute): StructField =
  StructField(attr.name, attr.data_type, attr.nullable)

def attributesToSchema(attrs: ListBuffer[Attribute]): StructType =
  StructType(attrs.map(attributeToStructField))

如果您不熟悉map函数:它已在所有集合中定义,并使用函数A => BListBuffer[A]变为ListBuffer[B](或任何其他集合)收集,就此而言)。您将在Scala和Spark中遇到这种高阶函数

答案 1 :(得分:2)

您发起了schema,但您从未在循环内将已添加的structfield分配回schema。这就是为什么添加的structFields未反映在已启动的schema中。

您应该使用DataTypes api灵活创建schema。以下是我的建议。希望它有所帮助

def create_schema_from_attr_list(attr_list: ListBuffer[Attribute]): StructType = {
  // create bufferedlist of structfield
  val bufferFields : util.ArrayList[StructField] = new util.ArrayList[StructField]
  // Add structfields
  for (i <- 0 until attr_list.length) {
    bufferFields.add(DataTypes.createStructField(attr_list(i).name, attr_list(i).data_type, attr_list(i).nullable))
  }
  DataTypes.createStructType(bufferFields)
}