2016-07-18 2 views
0

Я пытаюсь настроить RDD и собрать данные в построитель строк. Но это происходит не так, как foreach работает на узлах-исполнителях, а строковый конструктор работает на узле драйвера. является ли какой-либо способ достичь моей цели? Я не хочу использовать collect действие, как оно дорого.Соберите данные с помощью Foreach

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

Любая помощь очень ценится.

+3

Обзора ваших апача искры знания о возбудителе/​​рабочих (http://spark.apache.org/docs/latest/cluster-overview.html): ваш (строка) строитель живет в драйвере, ваша жизнь javaRDD на рабочих. Если вы хотите получить данные из javaRDD в свой строитель, вам необходимо «collect()». – WillemM

+0

Вы хотите сказать, что тер никак не отличается от collect()? – BDR

+0

Обновлен мой вопрос. Спасибо @WillemM – BDR

ответ

1

Вы можете использовать foreachPartition. Это будет собирать данные только у исполнителя, а не у водителя.

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

Может только перебирать массив или экземпляр java.lang.Iterable .... ..получение этой ошибки в foreach loop "for (String x: partition)" – BDR

+1

Извините, я не знаком с Java API. Раздел - это Итератор, а не Итерабельный. Попробуйте новый код. – Dikei

+0

Да. Я просто пробовал с циклом while. оно работает. это то, чего я ожидал. – BDR

1

Вы можете использовать rdd.aggregate для того, чтобы объединить все строки в вашем РДУ в один 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" 

Очевидно, что все содержимое строки вашего РДУ будет слита в строке буфера который имеет потенциал быть огромным, но это то, что вы хотели ... Это лучше, чем собирать, потому что строковые данные не отправляются «сырым» в драйвер (только в конкатенированной форме).

Также обратите внимание на порядок строк не гарантируется ...

1

Я думаю, что может быть альтернативным способом: Накопитель. Вот перенаправление о том, как использовать строку Накопитель:
Not able to declare String type accumulator
Заслуга автора этого ответ

+2

Не думал об этой опции, но не использовал бы аккумуляторы немного рискованно, так как если rdd вычисляется более одного раза, значение аккумулятора будет неправильным? –

+1

@HarelGliksman Вы правы, если не будете кэшировать его. Я отредактирую «лучший способ» на «альтернативном пути» – Vale

+0

@HarelGliksman Аккумуляторы безопасны при вызове внутри действия, такого как 'foreach'. – Dikei

Смежные вопросы