MapReduce课程设计 好友推荐功能

240 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天

一、算法说明

由图所示,我们先简单假设一个朋友圈,下面是好友之间的关系。

判断某两个人是否认识,并推荐为好友,并且某两个非好友的用户,他们的共同好友越多,那么他们越可能认识。

6162362f4b538ce0f7ed929eb01dfdd.jpg

1、直接相连的表示两个人是好友关系。 2、两个人有相同的好友表示两个人是间接好友。 3、好友推荐列表就是按照两个用户的共同好友数量排名。

二、思路分析 

1、推荐者与被推荐者一定有一个或多个相同的好友

2、全局去寻找好友列表中两两关系

3、去除直接好友

4、统计两两关系出现次数

三、详细步骤

3、1 数据准备:

每行首位为用户本人,后面的为其对应好友

注:每个名字之间有且只有一个空格分割

image.png

3、2 编码操作:

3、2、1 创建项目

3、2、2 代码编写 

  • FriendsRecommend.java
package org.hadoop.friend;
 
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;
 
public class FriendsRecommend {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
 
        job.setJarByClass(FriendsRecommend.class);
 
        Path input = new Path(args[0]);
        FileInputFormat.addInputPath(job, input);
 
        Path output = new Path(args[1]);
        //如果文件存在,,删除文件,方便后续调试代码
        if (output.getFileSystem(conf).exists(output)) {
            output.getFileSystem(conf).delete(output,true);
        }
 
        FileOutputFormat.setOutputPath(job, output);
 
        job.setMapperClass(FriendsRecommendMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        job.setReducerClass(FriendsRecommendReduce.class);
 
        job.waitForCompletion(true);
    }
}
  • FriendsRecommendMapper.java
package org.hadoop.friend;
 
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.util.StringUtils;
 
import java.io.IOException;
 
public class FriendsRecommendMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    Text mkey = new Text();
    IntWritable mval = new IntWritable();
 
    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        //不能用双引号,要用单引号 将传递过来的值进行分割
        String[] strs = StringUtils.split(value.toString(), ' ');
        // 直接好友的 key为直接好友列表  value为0
        for (int i = 1; i < strs.length; i++) {
            //直接好友关系
            mkey.set(fof(strs[0], strs[i]));
            mval.set(0);
            context.write(mkey, mval);
            //间接好友关系 设置value为1
            for (int j = i + 1; j < strs.length; j++) {
                mkey.set(fof(strs[i], strs[j]));
                mval.set(1);
                context.write(mkey, mval);
            }
        }
    }
 
    //两个共同好友的间接好友之间,可能存在 B C 和C B 的情况,但是比对累加时,计算机不识别,所以需要字典排序
    private static String fof(String str1, String str2) {
        //compareTo比较的 正数说明大
        if (str1.compareTo(str2) > 0) {
            return str2 + ":" + str1;
        }
        return str1 + ":" + str2;
    }
}

  • FriendsRecommendReducer.java
package org.hadoop.friend;
 
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
 
class FriendsRecommendReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
    IntWritable rval = new IntWritable();
 
    @Override
    protected void reduce(Text key, Iterable<IntWritable> vals,Context context)
            throws IOException, InterruptedException {
        int sum=0;
        for (IntWritable v : vals) {
            //发现直接是0的 是直接好友 舍弃
            if (v.get() ==0 ) {
                return ;
            }
            sum +=1;
        }
        rval.set(sum);
        context.write(key, rval);
    }
 
}

3、2、3 程序打包

  • 在父项目的maven视图下点击package进行打包

image.png

  •  打包成功后可以获得jar包

3、2、4 程序测试

cd /opt/testData/friend 进入friend文件,若没有testData 、friend文件夹可自行创建

  • 开启Hadoop集群
  • 把jar包上传到虚拟机node01里
  • 上传本地测试文件hello.txt到虚拟机

image.png 分布式文件系统创建input目录并且input目录上传测试文件friend.txt,执行程序

image.png

  •  查看结果

image.png

四、Web端查看结果

image.png