需求:实现用户好友推荐
- 当前有用户关系图,如下所示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e6bd4957eaff75092041d6b11e272d04.png)
- 对应的数据如下所示:用户
刘德华 周杰伦
刘德华 刘若英
王祖贤 齐秦
陈升 刘若英
刘若英 周传雄
周杰伦 齐秦
周杰伦 王祖贤
- 请开发MapReduce程序实现基于好友关系的推荐
- 例如,由于齐秦认识周杰伦、刘德华认识周杰伦,所以向刘德华推荐齐秦,向齐秦推荐刘德华
齐秦 刘德华
刘德华 齐秦
开发思路
step1:结果长什么样
- 结果有两列,都是人名
- 思路:如果两个用户有共同的好友,就推荐这两个用户认识
step2:Map输出的Key是什么
step3:Map输出的value是什么
step4:验证
用户 好友
key value
刘德华 周杰伦
周杰伦 刘德华
刘德华 刘若英
刘若英 刘德华
王祖贤 齐秦
齐秦 王祖贤
陈升 刘若英
刘若英 陈升
刘若英 周传雄
周传雄 刘若英
周杰伦 齐秦
齐秦 周杰伦
周杰伦 王祖贤
王祖贤 周杰伦
用户 好友列表
刘德华 周杰伦 刘若英
周杰伦 刘德华 齐秦 王祖贤
刘若英 刘德华 陈升 周传雄
王祖贤 齐秦 周杰伦
齐秦 王祖贤 周杰伦
陈升 刘若英
周传雄 刘若英
- Reduce
- 将每个用户的好友列表放入一个自定义的迭代器中
- 构建两层循环,实现两两推荐
- Reduce中输入的迭代器参数只能迭代一次
开发实现
Driver类
public class FriendMR extends Configured implements Tool {
@Override
public int run(String[] args) throws Exception {
Job job = Job.getInstance(this.getConf(),"friend");
job.setJarByClass(FriendMR.class);
TextInputFormat.setInputPaths(job,new Path("datas/friend/friendRelation.txt"));
job.setMapperClass(FriendMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setReducerClass(FriendReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
TextOutputFormat.setOutputPath(job,new Path("datas/output/friend1"));
return job.waitForCompletion(true) ? 0:-1;
}
public static void main(String[] args) {
Configuration conf = new Configuration();
try {
int status = ToolRunner.run(conf, new FriendMR(), args);
System.exit(status);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Mapper类
public class FriendMapper extends Mapper<LongWritable, Text,Text,Text> {
private Text outputKey = new Text();
private Text outputValue = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] relation = value.toString().split("\t");
String user = relation[0];
this.outputKey.set(user);
String friend = relation[1];
this.outputValue.set(friend);
context.write(this.outputKey,this.outputValue);
context.write(this.outputValue,this.outputKey);
}
}
Reduce类
public class FriendReduce extends Reducer<Text,Text,Text,Text> {
private Text outputKey = new Text();
private Text outputValue = new Text();
Set<String> sets = new HashSet<>();
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
sets.clear();
for (Text value : values) {
sets.add(value.toString());
}
if(sets.size() > 1){
for(Iterator<String> i = sets.iterator();i.hasNext();){
String user1 = i.next();
for(Iterator<String> j = sets.iterator();j.hasNext();){
String user2 = j.next();
if(!user1.equals(user2)){
this.outputKey.set(user1);
this.outputValue.set(user2);
context.write(this.outputKey,this.outputValue);
}
}
}
}
}
}