MapReduce模拟小型推荐系统

MapReduce实例-好友推荐

背景

好友关系图如下图所示

在这里插入图片描述

转化为文字之后为,即为输入数据

tom hello hadoop cat
world hadoop hello hive
cat tom hive
mr hive hello
hive cat hadoop world hello mr
hadoop tom hive world
hello tom world hive mr

思路

  • 推荐者与被推荐者一定有一个或多个相同的好友
  • 全局去寻找好友列表中两两关系
  • 去除直接好友
  • 统计两两关系出现次数

调用API

  • map:按好友列表输出两俩关系
  • reduce:sum两两关系
  • 再设计一个MR
  • 生成详细报表

编写Mapper

package com.sxt.FR;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.util.StringUtils;

import java.io.IOException;

/**
 * \* Project: FriendRecommended
 * \* Package: com.sxt.FR
 * \* Author: Hoodie_Willi
 * \* Date: 2019-08-17 13:27:40
 * \* Description:
 * \
 */

public class FMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
    Text tkey = new Text();
    IntWritable tval = new IntWritable();
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        //world hello hadoop cat
        String[] words = StringUtils.split(value.toString(), ' ');

        for (int i = 1; i < words.length; i++){
            // 把一对封装在tkey中
            tkey.set(getFd(words[0], words[i]));
            // 如果是直接好友,则直接输出0
            tval.set(0);
            // 用数组的第一个元素与后面的所有元素一一匹配,输出他们他们的直接好友关系
            context.write(tkey, tval);

            for (int j = i + 1; j < words.length; j++){
                // 把一对儿封装在tkey中
                tkey.set(getFd(words[i], words[j]));
                // 如果是潜在间接好友, 则直接输出1
                tval.set(1);
                // 用数组的第一个元素与后面的所有元素一一匹配,输出他们他们的直接好友关系
                context.write(tkey, tval);
            }
        }
    }
    private String getFd(String a, String b){
        return a.compareTo(b) > 0 ? b+":"+a : a+":"+b;
    }
}

编写Reducer

package com.sxt.FR;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * \* Project: FriendRecommended
 * \* Package: com.sxt.FR
 * \* Author: Hoodie_Willi
 * \* Date: 2019-08-17 13:31:17
 * \* Description:
 * \
 */
public class FReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    IntWritable tval = new IntWritable();
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        // 出现tom:hello 0代表两个人直接认识,不需要再去推荐
        // tom:hello 1
        // tom:hell0 1

        // 只考虑以下这种情况,两人间接认识的情况
        // hadoop:hive 1
        // hadoop:hive 1
        // hadoop:hive 1
        // hadoop:hive 1
        int num = 0;
        for (IntWritable val : values){
            if (val.get() == 0){
                return;
            }
            num++;
        }
        // 最终输出两个人之间的共同好友数
        tval.set(num);
        context.write(key, tval);
    }
}

编写主类

package com.sxt.FR;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 * \* Project: FriendRecommended
 * \* Package: com.sxt.FR
 * \* Author: Hoodie_Willi
 * \* Date: 2019-08-17 13:15:31
 * \* Description:
 * \
 */
public class MyFD {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        job.setJarByClass(MyFD.class);
        job.setJobName("friend");

        Path inPath = new Path("/user/fd/input");
        FileInputFormat.addInputPath(job, inPath);
        Path outPath = new Path("/user/fd/output");
        if (outPath.getFileSystem(conf).exists(outPath)){
            outPath.getFileSystem(conf).delete(outPath, true);
        }
        FileOutputFormat.setOutputPath(job, outPath);

        job.setMapperClass(FMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        job.setReducerClass(FReducer.class);
        job.waitForCompletion(true);
    }
}

结果

讲项目打包成jar包在放在namenode上运行

[root@node01 software]# hadoop jar FriendRecommended.jar com.sxt.FR.MyFD

查看输出数据为

cat:hadoop	2
cat:hello	2
cat:mr	1
cat:world	1
hadoop:hello	3
hadoop:mr	1
hive:tom	3
mr:tom	1
mr:world	2
tom:world	2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值