我有一个DataFrame,我想循环它的行并将其值添加到驱动程序可以使用的列表中?广播变量是只读的,据我所知,累加器仅用于求和。
有办法做到这一点吗?我正在使用spark 1.6.1
以下是在工作节点上运行的代码。我尝试将List传递给构造函数,但它似乎无法工作,因为一旦代码流传输到工作节点,它就不会向驱动程序返回任何值。
public class EnrichmentIdentifiersBuilder实现了Serializable {
/**
*
*/
private static final long serialVersionUID = 269187228897275370L;
private List<Map<String, String>> extractedIdentifiers;
public EnrichmentIdentifiersBuilder(List<Map<String, String>> extractedIdentifiers) {
//super();
this.extractedIdentifiers = extractedIdentifiers;
}
public void addIdentifiers(DataFrame identifiers)
{
final List<String> parameters=Arrays.asList(identifiers.schema().fieldNames());
identifiers.foreach(new MyFunction<Row, BoxedUnit>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public BoxedUnit apply(Row line)
{
for (int i = 0; i < parameters.size(); i++)
{
Map<String, String> identifier= new HashMap<>();
identifier.put(parameters.get(i), line.getString(i));
extractedIdentifiers.add(identifier);
}
return BoxedUnit.UNIT;
}
});
}
}
答案 0 :(得分:0)
您可以将行转换为映射,然后在驱动程序中收集结果,而不是尝试将列表公开给工作者:
this.extractedIdentifiers = identifiers.rdd().map(
new MyFunction<Row, Map<String, String>>() {
private static final long serialVersionUID = 1L;
@Override
public Map<String, String> apply(Row line)
{
Map<String, String> identifier= new HashMap<>();
for (int i = 0; i < parameters.size(); i++)
{
identifier.put(parameters.get(i), line.getString(i));
}
return identifier;
}
}).collect(); //This returns the list of maps...
这是正确的方法,因为并发修改(如果可能)会有问题。此代码将数组的每个元素转换为具有其值的映射,然后将所有映射作为列表收集回驱动程序。
答案 1 :(得分:0)
感谢您的想法!
我做了一些小改动才能做到这一点。这是代码,所以任何人都可能在将来需要它
public List<Map<String, String>> addIdentifiers(DataFrame identifiers)
{
final List<String> parameters=Arrays.asList(identifiers.schema().fieldNames());
List<Map<String, String>> extractedIdentifiers = new ArrayList<>();
extractedIdentifiers = identifiers.javaRDD().flatMap( new FlatMapFunction<Row, Map<String, String>>() {
/**
*
*/
private static final long serialVersionUID = -2369617506532322680L;
@Override
public List<Map<String, String>> call(Row line) throws Exception {
List<Map<String, String>> identifier= new ArrayList<>();
for (int i = 0; i < parameters.size(); i++)
{
Map<String, String> keyValue= new HashMap<>();
keyValue.put(parameters.get(i), line.getString(i));
identifier.add(keyValue);
}
return identifier;
}
}).collect();
return extractedIdentifiers;
}
此外,还有一个集合累加器,可以与问题中的代码一起使用,并且可以使用javaSparkContext.sc()生成.copulablecollection()