如何在Java中实现scala的以下代码段
我正在实现一个代码来动态地将多个列添加到一个数据帧中,其中的行中有空值 我在scala中找到了以下代码片段,其中使用了Dataframe对象的映射函数如何在Java中实现scala的以下代码段,java,scala,apache-spark,Java,Scala,Apache Spark,我正在实现一个代码来动态地将多个列添加到一个数据帧中,其中的行中有空值 我在scala中找到了以下代码片段,其中使用了Dataframe对象的映射函数 import org.apache.spark.sql.catalyst.encoders.RowEncoder import org.apache.spark.sql.types.{DataTypes, NullType, StructType} import org.apache.spark.sql.{DataFrame, Encoders,
import org.apache.spark.sql.catalyst.encoders.RowEncoder
import org.apache.spark.sql.types.{DataTypes, NullType, StructType}
import org.apache.spark.sql.{DataFrame, Encoders, Row, SparkSession}
import org.apache.spark.sql.functions.lit;
def addColumnsViaMap(df: DataFrame, words: List[String]): DataFrame = {
val encoder = RowEncoder.apply(getSchema(df, words))
df.map(mappingRows(df.schema)(words))(encoder)
}
private val mappingRows: StructType => List[String] => Row => Row =
(schema) => (words) => (row) => {
val addedCols: List[Any] = words.map(_=> null)
Row.merge(row, Row.fromSeq(addedCols))
}
private def getSchema(df: DataFrame, words: List[String]): StructType = {
var schema: StructType = df.schema
words.foreach(word => schema = schema.add(word, "string", false))
schema
}
我已经用java实现了以下两个函数
private StructType getSchema(Dataset<Row> df, List<String> cols){
StructType schema = df.schema();
cols.forEach(col -> schema.add(col, "int", true));
return schema;
}
private addColumnsViaMap(Dataset<Row> df, List<String> cols){
Encoder<Row> encoder1 =
RowEncoder.apply(dataConsolidationEngine.getSchema(df,cols));
df.map(new MapFunction<Set<String>, Row>() {
private static final long serialVersionUID = 1L;
@Override
public Row call(Set<String> cols) throws Exception {
// TODO Auto-generated method stub
}
}, encoder1);
}
private StructType getSchema(数据集df,列表cols){
StructType schema=df.schema();
forEach(col->schema.add(col,“int”,true));
返回模式;
}
私有addColumnsIAMAP(数据集df,列表列){
编码器1=
应用(dataConsolidationEngine.getSchema(df,cols));
map(新的MapFunction(){
私有静态最终长serialVersionUID=1L;
@凌驾
公用行调用(Set cols)引发异常{
//TODO自动生成的方法存根
}
},编码器1);
}
由于参数不匹配,addColumnsViaMap方法在解析匿名映射函数方法时出现编译错误
我不理解mappingRows的scala代码,尤其是下面的StructType=>List[String]=>Row=>Row=
(模式)=>(单词)=>(行)
这是什么意思
如何在Java中实现上述scala代码?private val mappingRows:StructType=>List[String]=>Row=>=
(架构)=>(单词)=>(行)=>{
val addedCols:List[Any]=words.map(=>null)
行合并(行,行fromSeq(addedCols))
}
简言之,这可以理解为:
mappingRows
是一个“函数”,它接受3个参数(类型分别为StructType
、List
和Row
,例如schema、words和Row),并返回一个行。但不是这样称呼它:
mappingRows(模式、单词、行)`
你会去的
mappingRows(模式)(单词)(行)
这意味着打电话只是
mappingRows(模式)(单词)
将返回一个函数,该函数接受行
,并返回行
:一个映射函数,可以传递给典型的.map()
函数
基本上,给定一个模式和一列列列名称,闭包接受一行作为输入。对于每个给定的col名称,它只是将null列添加到该行中
这有助于回答您的问题吗?private val mappingRows:StructType=>List[String]=>Row=>Row=
(架构)=>(单词)=>(行)=>{
val addedCols:List[Any]=words.map(=>null)
行合并(行,行fromSeq(addedCols))
}
简言之,这可以理解为:
mappingRows
是一个“函数”,它接受3个参数(类型分别为StructType
、List
和Row
,例如schema、words和Row),并返回一个行。但不是这样称呼它:
mappingRows(模式、单词、行)`
你会去的
mappingRows(模式)(单词)(行)
这意味着打电话只是
mappingRows(模式)(单词)
将返回一个函数,该函数接受行
,并返回行
:一个映射函数,可以传递给典型的.map()
函数
基本上,给定一个模式和一列列列名称,闭包接受一行作为输入。对于每个给定的col名称,它只是将null列添加到该行中
这有助于回答您的问题吗?好吧,这个声明有点复杂(我也有点不可读),所以让我们退一步
在scala中,字符串
,列表
。。。是每个人都知道的类型。您可以创建类型为String
的变量
您还可以将函数赋值给变量(这是scala的函数方向),这样函数也有类型。例如,如果您有一个函数,它接受一个列表
并输出一个字符串
,那么它的类型是List=>String
这在代码中看起来像吗
// A list of strings
val names = List("alice", "bob")
// A function that takes a list and returns a string
def listToString(list: List[String]): String = list.mkString(",")
// We can assign the function to a variable
val myListToString: List[String] => String = listToString
但是我们有一个较短的函数声明符号,我们可以将它们声明为“inline”,而不使用def
语句。这样就可以等效地编写上述代码:
val names = List("alice", "bob")
val myListToString: List[String] => String = (list) => list.mkString(",")
因此,一般来说:
A=>B
是一种函数类型,它接受A
并返回B
(arg:A)=>{new B()}
是一个实际函数,它以A
的一个实例作为输入(该实例绑定到变量名arg
,其主体返回B的一个实例)
现在让我们做一些疯狂的事情,让我们…重新开始。假设F
是一个函数,它接受列表
并返回字符串
。一个接受Int
并返回F
的函数看起来像什么
那么应该是:
Int=>F
- 也就是说:
Int=>(List=>String)
- 可以写入
Int=>List=>String
你怎么申报呢
// Borrowing from above
val names = List("alice", "bob")
val myListToString: List[String] => String = (list) => list.mkString(",")
// now we're doing it
val intToListToString = (integerValue) => myListToString
// now we're doing it in one go
val intToListToString2 = (integerValue) => (list) => list.mkString(",")
这里,intToListToString
是一个函数,它接受int
并返回“一个接受列表
并返回字符串的函数”
你可以一次又一次地筑巢
直到您得到:StructType=>List[String]=>Row=>Row
这是一种类型,意思是“一个函数,它以StructType
作为输入并返回(一个函数,它以List[String]
作为输入并返回一行))
您可以将其实现为:
(schema) => // a function that takes schema, and returns
(words) => // a function that takes a list of words and returns
(row) => // a function that takes a row and returns
Row.fromSeq(...) // another row
现在在Java中会是什么样子
如果你想严格地转换它,你可以这样想:scala的A=>B
的自然等价物是java.util.Function
。最重要的是,如果你想使用一个函数来执行Sparkmap
操作
schema -> words -> row -> Row.merge(row, Row.fromSeq(Array.newInstance(String.class, words.size)))
import org.apache.spark.sql.DataFrame
def addColumnsViaMap(dataframe: DataFrame, words: List[String]) = words.foldLeft(dataframe)((df, word) => df.withColumn(word, lit(null: String)))
val dataframe = Seq(("a", "b"), ("c", "d")).toDF("columnA", "columnB")
val words = List("columnC", "columnD")
addColumnsViaMap(dataframe, words).show
+-------+-------+-------+-------+
|columnA|columnB|columnC|columnD|
+-------+-------+-------+-------+
| a| b| null| null|
| c| d| null| null|
+-------+-------+-------+-------+
DataFrame addColumnsViaMap(DataFrame dataframe, List<String> words) {
for (String word: words) {
dataframe = dataframe.withColumn(word, lit((String) null))
}
return dataframe;
}