Map器和reducer函数的输出到底是什么

9fkzdhlc  于 2021-05-29  发布在  Hadoop
关注(0)|答案(3)|浏览(448)

这是使用mapreduce和hadoop提取包含特定值的行的后续问题
Map器函数

  1. public static class MapForWordCount extends Mapper<Object, Text, Text, IntWritable>{
  2. private IntWritable saleValue = new IntWritable();
  3. private Text rangeValue = new Text();
  4. public void map(Object key, Text value, Context con) throws IOException, InterruptedException
  5. {
  6. String line = value.toString();
  7. String[] words = line.split(",");
  8. for(String word: words )
  9. {
  10. if(words[3].equals("40")){
  11. saleValue.set(Integer.parseInt(words[0]));
  12. rangeValue.set(words[3]);
  13. con.write( rangeValue , saleValue );
  14. }
  15. }
  16. }
  17. }

减速机功能

  1. public static class ReduceForWordCount extends Reducer<Text, IntWritable, Text, IntWritable>
  2. {
  3. private IntWritable result = new IntWritable();
  4. public void reduce(Text word, Iterable<IntWritable> values, Context con) throws IOException, InterruptedException
  5. {
  6. for(IntWritable value : values)
  7. {
  8. result.set(value.get());
  9. con.write(word, result);
  10. }
  11. }
  12. }

获得的输出为

  1. 40 105
  2. 40 105
  3. 40 105
  4. 40 105

编辑1:但预期的输出是

  1. 40 102
  2. 40 104
  3. 40 105

我做错什么了?
在mapper和reducer函数中到底发生了什么?

wgeznvg7

wgeznvg71#

到底发生了什么
您正在使用逗号分隔的文本行,拆分逗号,并过滤掉一些值。 con.write() 如果您所做的只是提取这些值,则每行只应调用一次。
Map器将对您输出的所有“40”键进行分组,并形成一个用该键编写的所有值的列表。这就是减速机的读数。
你应该试试这个Map功能。

  1. // Set the values to write
  2. saleValue.set(Integer.parseInt(words[0]));
  3. rangeValue.set(words[3]);
  4. // Filter out only the 40s
  5. if(words[3].equals("40")) {
  6. // Write out "(40, safeValue)" words.length times
  7. for(String word: words )
  8. {
  9. con.write( rangeValue , saleValue );
  10. }
  11. }

如果不希望分割字符串的长度有重复的值,那么就去掉for循环。
你的减缩器所做的只是打印出它从Map器收到的信息。

展开查看全部
pgky5nke

pgky5nke2#

在原始问题的上下文中-在复制条目时,不需要Map器或缩减器中的循环:

  1. public static class MapForWordCount extends Mapper<Object, Text, Text, IntWritable>{
  2. private IntWritable saleValue = new IntWritable();
  3. private Text rangeValue = new Text();
  4. public void map(Object key, Text value, Context con) throws IOException, InterruptedException
  5. {
  6. String line = value.toString();
  7. String[] words = line.split(",");
  8. if(words[3].equals("40")){
  9. saleValue.set(Integer.parseInt(words[0]));
  10. rangeValue.set(words[3]);
  11. con.write(rangeValue , saleValue );
  12. }
  13. }
  14. }

在reducer中,正如@serhiy在最初的问题中建议的那样,您只需要一行代码:

  1. public static class ReduceForWordCount extends Reducer<Text, IntWritable, Text, IntWritable>
  2. {
  3. private IntWritable result = new IntWritable();
  4. public void reduce(Text word, Iterable<IntWritable> values, Context con) throws IOException, InterruptedException
  5. {
  6. con.write(word, null);
  7. }

重读“编辑1”-我会留下一个琐碎的做法:)

展开查看全部
brgchamk

brgchamk3#

Map器输出如下:

  1. <word,count>

减速器输出如下:

  1. <unique word, its total count>

例句:读一行字,把其中所有的字都数出来,放进一张纸里 <key,value> 一对:

  1. <40,1>
  2. <140,1>
  3. <50,1>
  4. <40,1> ..

这里是40,50140。。是所有键,该值是该键在一行中出现的次数。这在Map器中发生。
那么,这些 key,value 成对的密钥被发送到reducer,在那里相似的密钥都被缩减为一个 key 与该键相关联的所有值相加,为该键-值对提供一个值。减速机的结果是:

  1. <40,10>
  2. <50,5>
  3. ...

在你的情况下,减速机没有任何作用。Map器找到的唯一值/单词仅作为输出。
理想情况下,你应该减少并得到这样的输出:“40150”被发现5次在同一行。

展开查看全部

相关问题