如何使用foreach迭代JavaRDD并使用spark java

时间:2017-12-14 07:13:22

标签: java apache-spark

我的文本文件中有这些行:

Some different lines....

Name : Praveen  
Age : 24  
Contact : 1234567890  
Location : India  

Some different lines....

Name : John  
Contact : 1234567890  
Location : UK  

Some different lines....  

Name : Joe  
Age : 54  
Contact : 1234567890  
Location : US  

一些不同的行表示中间还有其他信息。

现在我需要阅读文件并提取人员信息。如果缺少任何键,则应将其读作空字符串(第二人称信息中缺少年龄)。

JavaRDD<String> data = jsc.textFile("person.report");

List<String> name = data.filter(f -> f.contains("Name")).collect();
List<String> age = data.filter(f -> f.contains("Age")).collect();
List<String> contact = data.filter(f -> f.contains("Contact")).collect();
List<String> location = data.filter(f -> f.contains("Location")).collect();

当我以上述方式进行并迭代for循环时,第3个人的年龄将被分配给第2个人。

1 个答案:

答案 0 :(得分:3)

首先,你正在收集驱动程序上的所有内容,你确定这是你想做的吗?它不适用于大数据集...

基本上,您的问题是您认为记录不在一条线上。默认情况下,spark将每行视为一个单独的记录。然而,在这里,您的记录分为几行(姓名,年龄,地点......)。要解决这个问题,您需要找到另一个分隔符。如果在&#34;某些不同的行&#34;,有一个特定的字符串,请使用它并设置此属性:

sc.hadoopConfiguration.set("textinputformat.record.delimiter","specific string")

然后你可以这样写:

val cols = Seq("Name","Age", "Contact", "Location")
sc.textFile("...")
  .map( _.split("\n"))
  .map(x => cols
       .map( col => x.find(_.startsWith(col)).getOrElse(col+" :") ) )

与人对应的所有行都将在同一记录中,供您根据需要进行处理。如果找不到合适的分隔符,您的记录可能都有一个名称,因此您可以使用&#34;名称:&#34;。

在java8中,您可以使用流以相同的方式实现它。这有点冗长但是因为问题是java,你去了:

String[] array = {"Name", "Age", "Contact", "Location"};
List<String> list = Arrays.asList(array);
sc.textFile("...")
    .map(x -> Arrays.asList(x.split("\n")))
    .map(x -> list.stream()
                  .map(col -> x.stream()
                               .filter(line -> line.startsWith(col))
                               .findAny()
                               .orElse(col+" :"))
                  .collect(Collectors.toList()) );