【问题标题】:Collect data with Foreach使用 Foreach 收集数据
【发布时间】:2016-07-18 06:19:28
【问题描述】:

我正在尝试 foreach 一个 RDD 并将数据收集到一个字符串构建器中。但这并没有发生,因为 foreach 在执行程序节点上运行,而字符串生成器在驱动程序节点上运行。有什么方法可以实现我的目标吗?我不想使用 collect 操作,因为它很昂贵。

private static StringBuilder collect(JavaRDD<String> javaRDD) {
        StringBuilder builder = new StringBuilder();
        javaRDD.foreach(x -> builder.append(x));
        System.out.println(builder.toString() + " ****");
         return builder;
    }

高度赞赏任何帮助。

【问题讨论】:

  • 查看您关于驱动程序/工作人员 (spark.apache.org/docs/latest/cluster-overview.html) 的 apache spark 知识:您的(字符串)构建器存在于驱动程序中,您的 javaRDD 存在于工作人员上。如果你想从 javaRDD 获取数据到你的构建器中,你需要'collect()'。
  • 你的意思是说,ter 不是 collect() 以外的方法吗?
  • 更新了我的问题。谢谢@WillemM
  • 是的。 (或者它的变种就像 take(x))
  • Foreach 将在 executor/slave 节点中执行,当您调用 Collect() 时,来自从节点的所有数据都将被拉到 driver program 。当您处理 TB 的数据时,这是不行的。我希望有一种替代方法来实现我的目标。

标签: apache-spark java-8 rdd


【解决方案1】:

您可以使用foreachPartition。这只会收集 executor 上的数据,而不是驱动程序中的数据。

javaRDD.foreachPartition(partition -> {
  StringBuilder builder = new StringBuilder();
  while (partition.hasNext()) {
    builder.append(partition.next());
  }
  System.out.println(builder.toString() + " ****");
});

【讨论】:

  • 只能遍历数组或 java.lang.Iterable 的实例......在 foreach 循环“for(String x: partition)”时出现此错误
  • 对不起,我不熟悉 Java API。 Partition 是一个迭代器,而不是一个迭代器。试试新代码。
  • 是的。我刚刚尝试了while循环。有用。这是我的预期。
【解决方案2】:

我认为可能有另一种方式:累加器。以下是有关如何使用字符串累加器的重定向:
Not able to declare String type accumulator
归功于该回复的作者

【讨论】:

  • 没有想到这个选项,但是不使用累加器有点冒险,因为如果 rdd 被计算多次,累加器的值就不正确了?
  • @HarelGliksman 你是对的,除非你缓存它。我将以“替代方式”编辑“更好的方式”
  • @HarelGliksman 累加器在 foreach 等操作中调用时是安全的。
  • 真正的 Dikei,认为值得一提的是风险,因为 foreach 并不是人们可能尝试将它们用于此目的的唯一方式......
【解决方案3】:

您可以使用 rdd.aggregate 将 rdd 中的所有字符串组合成一个 StringBuffer,如下所示:

val rdd = sc.parallelize( List( "h" , "a" , "b" ) )
val res = rdd.aggregate( new StringBuffer )( ( sb:StringBuffer , str : String ) => sb.append( str ) , ( sb1 : StringBuffer , sb2 : StringBuffer ) => sb1.append( sb2 ) )
println( res ) // "abh"

显然,你的 rdd 字符串的全部内容将连接在字符串缓冲区中,这可能是巨大的,但这就是你想要的...... 这比收集要好,因为字符串数据不会“原始”传送到驱动程序(仅以串联形式)。

还要注意不保证字符串的顺序...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多