mapreduce的核心思想就是:map读入一条记录,然后重置其key 、value;reduce针对map的同一条key,把其values整合,然后重新输出key、value;
这两天做mapreduce时,忽然有种想法:针对一行记录,是否有输出多行记录,包含有不同到key,value,的情况;这种情况到应用是否有好处呢?
假设有这样的一个数据:其中第一列代表用户的标识,第二列代表书籍的标识
1,A
1,B
1,C
2,A
2,B
3,B
3,C
4,A
4,E
5,C
5,E
1,A---》2,4;E,B
1,B---》3,2;A,C
。。。
那现在看下,我们可以如何操作呢?很直观的两种想法:一,以用户标识作为key,书籍标识作为value,那么经过mapreduce后,我们得到到数据如下:
1---》A,B,C
2---》A,B
。。。
或者以书籍标识作为key ,以用户标识作为value,那么我们得到的数据如下:
A--》1,2,4
B--》1,2,3
.。。
这两种情况都很难做到我们要的输出,那么如何做呢?就用文章开始说过的方法:一条记录产生多条key/value:
下面就具体代码进行分析:
第一个Mapper:
package org.fansy.data907;
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/*
* first map input: 1,A
* 1,A
* 1,B
* reduce output: 1 /t A,B,C,
*/
public class BookM extends Mapper<LongWritable,Text,Text,Text>{
public void map(LongWritable key,Text line,Context context)throws IOException,InterruptedException{
String[] values=line.toString().split(",");
if(values.length!=2){
return;
}
String userid=values[0];
String bookid=values[1];
context.write(new Text(userid), new Text(bookid));
}
}
第一个Reducer:
package org.fansy.data907;
import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class BookR extends Reducer<Text,Text,Text,Text>{
public void reduce(Text key,Iterable<Text> values,Context context)throws IOException,
InterruptedException{
StringBuffer sb=new StringBuffer();
for(Text val:values){
sb.append(val.toString());
sb.append(",");
}
context.write(key, new Text(sb.toString()));
}
}
第一个M/R的操作是输出用户标识和其所看过的所有书籍,这个和第一种操作一样,输出如下&#x