MapReduce--实现好友推荐

需求:实现用户好友推荐

  • 当前有用户关系图,如下所示
    在这里插入图片描述
  • 对应的数据如下所示:用户
刘德华	周杰伦
刘德华	刘若英
王祖贤	齐秦
陈升	刘若英
刘若英	周传雄
周杰伦	齐秦
周杰伦	王祖贤
  • 请开发MapReduce程序实现基于好友关系的推荐
    • 例如,由于齐秦认识周杰伦、刘德华认识周杰伦,所以向刘德华推荐齐秦,向齐秦推荐刘德华
      • 就会得到结果如下:
齐秦	刘德华
刘德华	齐秦

开发思路

step1:结果长什么样

  • 结果有两列,都是人名
  • 思路:如果两个用户有共同的好友,就推荐这两个用户认识
    • 将一个用户的所有好友,两两推荐

step2:Map输出的Key是什么

  • 按照每个用户进行分组
  • 用户

step3:Map输出的value是什么

  • value:这个用户的好友

step4:验证

  • Map
用户		好友
key		value
刘德华	周杰伦
周杰伦 刘德华
刘德华	刘若英
刘若英 刘德华
王祖贤	齐秦
齐秦 王祖贤	
陈升	刘若英
刘若英 陈升
刘若英	周传雄
周传雄 刘若英	
周杰伦	齐秦
齐秦 周杰伦
周杰伦	王祖贤
王祖贤 周杰伦
  • Shuffle:分组,相同用户的好友放在一起
用户			好友列表
刘德华		周杰伦 刘若英
周杰伦 	刘德华 齐秦 王祖贤
刘若英 	刘德华 陈升 周传雄
王祖贤		齐秦 周杰伦
齐秦 		王祖贤 周杰伦
陈升		刘若英
周传雄 	刘若英	
  • 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) {
        //调用run方法
        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();
        //将当前用户的所有好友,放入set集合
        for (Text value : values) {
            sets.add(value.toString());
        }
        //如果你的好友个数大于1个,取好友列表中的两个好友进行推荐
        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);
                    }
                }
            }
        }
    }
}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
社交好友推荐是一个经典的推荐系统问题,MapReduce是一个用于大规模数据处理的框架,结合起来可以高效地解决这个问题。实现思路如下: 1. 读取用户关系数据:从输入文件中读取用户关系数据,每行表示一个用户关系,例如:A B表示A和B是好友关系。 2. Map阶段:将每个用户看作一个键,将该用户的好友列表作为值,输出(key, value)键值对到中间结果中。 3. Reduce阶段:对于每个用户,将其所有好友列表合并起来,去掉重复的好友,得到该用户的所有好友集合。然后根据好友的共同好友数进行推荐,将共同好友数最多的前N个用户作为推荐好友列表,将推荐结果输出到输出文件中。 以下是代码实现(使用Python语言和Hadoop框架): Mapper代码: ```python #!/usr/bin/env python import sys # 处理每一行输入数据 for line in sys.stdin: # 去掉前后空格 line = line.strip() # 按照空格分隔输入数据,得到两个用户之间的好友关系 users = line.split() # 输出每个用户及其好友列表 for user in users: friends = [u for u in users if u != user] print '%s\t%s' % (user, ','.join(friends)) ``` Reducer代码: ```python #!/usr/bin/env python import sys # 推荐列表大小 N = 10 # 处理每个用户的好友列表 def process_friends(friends_list): # 将所有好友列表合并起来 all_friends = [] for friends in friends_list: all_friends += friends.split(',') # 去掉重复的好友 all_friends = list(set(all_friends)) # 统计每个好友出现的次数 count = {} for friend in all_friends: count[friend] = count.get(friend, 0) + 1 # 按照好友出现次数从大到小排序 sorted_count = sorted(count.items(), key=lambda x: x[1], reverse=True) # 返回推荐列表 return [f[0] for f in sorted_count[:N]] # 处理每个用户的好友列表 current_user = None friends_list = [] for line in sys.stdin: # 去掉前后空格 line = line.strip() # 将输入数据按照键值分隔开 user, friends = line.split('\t', 1) # 如果是新用户,则输出该用户的推荐列表 if user != current_user and current_user is not None: recommended_friends = process_friends(friends_list) print '%s\t%s' % (current_user, ','.join(recommended_friends)) friends_list = [] # 添加当前用户的好友列表 friends_list.append(friends) current_user = user # 输出最后一个用户的推荐列表 if current_user is not None: recommended_friends = process_friends(friends_list) print '%s\t%s' % (current_user, ','.join(recommended_friends)) ``` 执行MapReduce作业的命令: ```shell hadoop jar path/to/hadoop-streaming.jar \ -input input_path \ -output output_path \ -mapper mapper.py \ -reducer reducer.py \ -file mapper.py \ -file reducer.py ``` 其中,`path/to/hadoop-streaming.jar`为Hadoop Streaming的jar包路径,`input_path`为输入文件路径,`output_path`为输出文件路径,`mapper.py`和`reducer.py`为上述Mapper和Reducer代码的文件名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值