如何在mapper输出中收集三个参数。有什么办法

时间:2012-11-08 12:11:46

标签: hadoop mapreduce

我是新手绘制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);
}

2 个答案:

答案 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));