我是新手绘制Reduce和hadoop概念。所以请帮忙
我有大约100个包含此格式数据的文件
conf/iceis/GochenouerT01a:::John E. Gochenouer::Michael L. Tyler:::Voyeurism, Exhibitionism, and Privacy on the Internet.
我应该通过map reduce算法来做。现在在输出中我想显示
John E. Gochenoue Voyeurism .
John E. Gochenoue Exhibitionism
John E. Gochenoue and
John E. Gochenoue privacy
John E. Gochenoue on
John E. Gochenoue the
John E. Gochenoue internet
Michael L. Tyler Voyeurism .
Michael L. Tyler Exhibitionism
Michael L. Tyler and
Michael L. Tyler privacy
Michael L. Tyler on
Michael L. Tyler the
Michael L. Tyler internet
现在它是单行。因此,有很多行,包含大量的名字和大量的书籍。
因此,如果我考虑一个110行的文档。我可以像这样输出我的mapper
John E. Gochenoue Voyeurism 1
John E. Gochenoue Exhibitionism 3
Michael L. Tyler on 7
即。 要说它显示名称和工作后跟文档中单词的遮挡,最后在缩小之后,应显示名称,后跟名称对其的单词以及它在'n中出现的单词的组合频率'文件。
我知道output.collecter()但它需要两个参数
output.collect(arg0, arg1)
是否有任何方法可以收集三个值,如名称,单词和单词
以下是我的代码
public static class Map extends MapReduceBase implements
Mapper<LongWritable, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value,
OutputCollector<Text, IntWritable> output, Reporter reporter)
throws IOException {
String line = value.toString();
/*
* StringTokenizer tokenizer = new StringTokenizer(line); while
* (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken());
* output.collect(word, one);
*/
String strToSplit[] = line.split(":::");
String end = strToSplit[strToSplit.length - 1];
String[] names = strToSplit[1].split("::");
for (String name : names) {
StringTokenizer tokens = new StringTokenizer(end, " ");
while (tokens.hasMoreElements()) {
output.collect(arg0, arg1)
System.out.println(tokens.nextElement());
}
}
}
}
public static class Reduce extends MapReduceBase implements
Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterator<IntWritable> values,
OutputCollector<Text, IntWritable> output, Reporter reporter)
throws IOException {
int sum = 0;
while (values.hasNext()) {
sum += values.next().get();
}
output.collect(key, new IntWritable(sum));
}
}
public static void main(String[] args) throws Exception {
JobConf conf = new JobConf(example.class);
conf.setJobName("wordcount");
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.class);
conf.setMapperClass(Map.class);
conf.setCombinerClass(Reduce.class);
conf.setReducerClass(Reduce.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, "/home/vishal/workspace/hw3data");
FileOutputFormat.setOutputPath(conf,
new Path("/home/vishal/nmnmnmnmnm"));
JobClient.runJob(conf);
}
答案 0 :(得分:2)
诀窍是编写一个Text(hadoop Writable实现之一),其字符串内容是多个以制表符分隔的值。这就是你可以轻松地在映射器和缩减器之间传递复杂值的方法。
当然,更多的工业强度方法是编写自己的Writable。 Writable基本上是具有特殊序列化/反序列化行为的pojo。在这种情况下,您的可写将具有三个属性。
答案 1 :(得分:0)
对于映射器类在传递标记化字符串时,您需要在计算时对相同的键进行基本分组。
这意味着计算一个人使用单词的次数需要您生成一个类似于John Smith<delimiter>Word
的密钥。分隔符可以是您想要的任何内容。大多数人使用制表符,以便在最终的减速器输出中保持TSV。
所以要纠正你的output.collect语句就是把它改成这样的东西:
output.collect(new Text(name + "\t" + tokens.nextElement()), new IntWritable(1));