вы также можете использовать linq и анонимные типы для достижения того же результата с гораздо меньшим количеством кода, описанным здесь здесь .
UPDATE: блог отключен, вот содержание:
(..) Значения, указанные в таблице, представляют собой длину строк вместо строковых значений (!). Это может показаться странным, но механизм привязки по умолчанию работает по умолчанию - с учетом объекта, который он попытается связать с первое свойство этого объекта (первое свойство, которое оно может найти). Когда передан экземпляр класса String, к которому он привязан, является String.Length, так как нет другого свойства, которое обеспечивало бы собственно строку.
Это означает, что для получения нашего права привязки нам нужен объект-оболочка, который будет показывать фактическое значение строки как свойство:
public class StringWrapper
{
string stringValue;
public string StringValue { get { return stringValue; } set { stringValue = value; } }
public StringWrapper(string s)
{
StringValue = s;
}
}
List testData = new List();
// add data to the list / convert list of strings to list of string wrappers
Table1.SetDataBinding(testdata);
Хотя это решение работает так, как ожидалось, требует довольно много строк кода (в основном для преобразования списка строк в список оберток строк).
Мы можем улучшить это решение с помощью LINQ и анонимных типов - мы будем использовать запрос LINQ для создания нового списка строковых оболочек (в нашем случае строковая оболочка будет анонимным).
var values = from data in testData select new { Value = data };
Table1.SetDataBinding(values.ToList());
Последнее изменение, которое мы собираемся сделать, - переместить код LINQ в метод расширения:
public static class StringExtensions
{
public static IEnumerable CreateStringWrapperForBinding(this IEnumerable strings)
{
var values = from data in strings
select new { Value = data };
return values.ToList();
}
Таким образом, мы можем повторно использовать код, вызывая один метод для любой коллекции строк:
Table1.SetDataBinding(testData.CreateStringWrapperForBinding());
.toLocalIterator().map(...).forEach(...add to Seq)
Это обработает разделы 'по одному' на драйвере (по сравнению с размещением всего RDD в память драйвера). Память, требуемая на драйвере, равна размеру самого большого раздела.
Тест, если Seq впишется в память драйвера:
.map(x => x.name).collect().toSeq()
Этот метод уменьшит размер RDD (и его разделы) прежде, чем отправить данные на драйвер. Если это заставляет драйвер исчерпывать память тогда, единственная опция состоит в том, чтобы увеличить память драйвера.
Примечания здесь:
https://spark.apache.org/docs/2.2.0/api/java/org/apache/spark/rdd/RDD.html#collect https://spark.apache.org/docs/2.2.0/api/java/org/apache/spark/rdd/RDD.html#toLocalIterator