我的文本文件中有这些行:
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个人。
答案 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()) );