编辑工作节点在驱动程序中定义的列表

时间:2018-01-19 17:35:20

标签: java apache-spark apache-spark-sql spark-dataframe

我有一个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;
        }
    });

}

}

2 个答案:

答案 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()