技术标签: 算法 好友推荐 mapreduce hadoop 大数据
好友关系如图:
1、直接相连的表示两个人是直接好友关系;
2、两个人有相同的好友表示两个人是间接好友(当然可能两个人同时也是直接好友,如图hello和hive)。
3、好友推荐列表就是按照两个用户的共同好友数量排名
1、分两步MapReduce计算完成;
2、第一步先得到用户的间接好友关系数目,注意有直接好友关系的用户需要过滤掉;
3、第二步根据间接好友关系数就可以得到用户推荐列表。
tom hello hadoop cat
word hadoop hello hive
cat tom hive
mr hive hello
hive cat hadoop word hello mr
hadoop tom hive word
hello tom word hive mr
第一个是当前用户,后面的是其好友列表
一、mapper输出两种数据
1、对各用户的好友列表好友俩俩组合,输出间接好友关系;
2、当前用户和好友列表好友一一组合,输出直接好友关系。
注意!!!这里好友关系key需要顺序排序,避免重复记录,如hello:tom和tom:hello都表示同样两个人的关系。
public class FriendMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
private final Text text = new Text();
private final IntWritable mval = new IntWritable();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//样本数据:tom hello hadoop cat
String[] users = StringUtils.split(value.toString(), ' ');
for (int i = 1; i < users.length; i++) {
//和好友组成直接关系,组合好友关系按顺序排列,确保user1和user2不会因为顺序问题,而被认为是两对关系
text.set(MrCommUtil.orderConcat(users[0], users[i]));
mval.set(0);
context.write(text, mval);
for (int j = i + 1; j < users.length; j++) {
//列表好友俩俩组合间接关系
text.set(MrCommUtil.orderConcat(users[i], users[j]));
mval.set(1);
context.write(text, mval);
}
}
}
}
二、reducer统计同两个用户的间接关系数,并过滤已经是直接关系的一组用户。
public class FriendReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private final IntWritable rval = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
//数据样本
//hadoop word 0
//hadoop word 1
//hadoop word 0
int num = 0;
for (IntWritable value : values) {
if (value.get() == 0) {
return;
}
num += 1;
}
rval.set(num);
context.write(key, rval);
}
}
三、输出结果集如下
cat:hadoop 2
cat:hello 2
cat:mr 1
cat:word 1
hadoop:hello 3
hadoop:mr 1
hive:tom 3
mr:tom 1
mr:word 2
tom:word 2
一、mapper输入数据集为第一步的结果集,map把记录映射成正反两组
public class Friend2Mapper extends Mapper<LongWritable, Text, FriendRelation, IntWritable> {
private final FriendRelation mkey = new FriendRelation();
private final IntWritable mval = new IntWritable();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//数据样本:cat:hadoop 2
String[] strs = StringUtils.split(value.toString(), '\t');
String[] users = StringUtils.split(strs[0], ':');
mkey.setFrom(users[0]);
mkey.setTo(users[1]);
int n = Integer.parseInt(strs[1]);
mkey.setN(n);
mval.set(n);
context.write(mkey, mval);
mkey.setFrom(users[1]);
mkey.setTo(users[0]);
context.write(mkey, mval);
}
}
二、排序比价器根据第一个用户和关系数倒排序
public class Friend2SortComparator extends WritableComparator {
public Friend2SortComparator() {
super(FriendRelation.class, true);
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
//排序先根据from,同from再根据n排倒序
FriendRelation f1 = (FriendRelation) a;
FriendRelation f2 = (FriendRelation) b;
int i = f1.getFrom().compareTo(f2.getFrom());
if (i == 0) {
return -Integer.compare(f1.getN(), f2.getN());
}
return i;
}
}
三、分组比较器根据第一个用户分组
public class Friend2GroupComparator extends WritableComparator {
public Friend2GroupComparator() {
super(FriendRelation.class, true);
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
//分组只根据from分组
FriendRelation f1 = (FriendRelation) a;
FriendRelation f2 = (FriendRelation) b;
int i = f1.getFrom().compareTo(f2.getFrom());
return i;
}
}
四、reduce取出关系数最大的推荐关系
public class Friend2Reducer extends Reducer<FriendRelation, IntWritable, Text, IntWritable> {
private final Text rkev= new Text();
private final IntWritable rval = new IntWritable();
@Override
protected void reduce(FriendRelation key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
//样本数据:
//cat:hadoop 2
// cat:hello 2
// cat:mr 1
// cat:word 1
int n = key.getN();
//输出最大间接关系数的所有推荐
for (IntWritable value : values) {
if (n != value.get()) {
break;
}
rkev.set(key.getFrom() + "->" + key.getTo());
rval.set(key.getN());
context.write(rkev, rval);
}
}
}
五、输出最终结果,用户推荐分最高的前两名
cat->hello 2
cat->hadoop 2
hadoop->hello 3
hello->hadoop 3
hive->tom 3
mr->word 2
tom->hive 3
word->mr 2
word->tom 2
六、完整代码及测试数据详见码云:hadoop-test传送门
文章浏览阅读2.1k次。原文链接先说说编解码问题编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 Eg:str1.decode('gb2312') #将gb2312编码的字符串转换成unicode编码str2.encode('gb2312') #将unicode编码..._python中encode在什么模块
文章浏览阅读949次,点赞21次,收藏15次。本文介绍了Java中的数据输入流(DataInputStream)和数据输出流(DataOutputStream)的使用方法。
文章浏览阅读111次。ie无法兼容_ie 浏览器 newdate
文章浏览阅读239次。这篇文章把 Docker 和 K8s 的关系给大家做了一个解答,希望还在迟疑自己现有的知识储备能不能直接学 K8s 的,赶紧行动起来,K8s 是典型的入门有点难,后面越用越香。
文章浏览阅读561次。ADI中文手册获取方法_adi 如何查看数据手册
文章浏览阅读1k次,点赞4次,收藏3次。React 获取接口数据实现分页效果以拼多多接口为例实现思路加载前 加载动画加载后 判断有内容的时候 无内容的时候用到的知识点1、动画效果(用在加载前,加载之后就隐藏或关闭,用开关效果即可)2、axios请求3、map渲染页面4、分页插件(antd)代码实现import React, { Component } from 'react';//引入axiosimport axios from 'axios';//引入antd插件import { Pagination }_react 分页
文章浏览阅读449次,点赞9次,收藏7次。这个变量与验签过程中的SignatureVerificationFilter::PUT_MESSAGE这个宏是对应的,SignatureVerificationFilter::PUT_MESSAGE,如果在签名过程中putMessage设置为true,则在验签过程中需要添加SignatureVerificationFilter::PUT_MESSAGE。项目中使用到了CryPtopp库进行RSA签名与验签,但是在使用过程中反复提示无效的数字签名。否则就会出现文章开头出现的数字签名无效。_cryptopp 签名
文章浏览阅读848次。新闻稿是新闻从业者经常使用的一种文体,它的格式与内容都有着一定的规范。本文将从新闻稿的格式和范文两个方面进行介绍,以帮助读者更好地了解新闻稿的写作_新闻稿时间应该放在什么位置
文章浏览阅读1.7k次。Java中的转换器设计模式 在这篇文章中,我们将讨论 Java / J2EE项目中最常用的 Converter Design Pattern。由于Java8 功能不仅提供了相应类型之间的通用双向转换方式,而且还提供了转换相同类型对象集合的常用方法,从而将样板代码减少到绝对最小值。我们使用Java8 功能编写了..._java转换器模式
文章浏览阅读150次。1,kubectl run创建pods[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1[root@master ~]# kubectl get podsNAME READY STATUS REST...
文章浏览阅读128次。PAT菜鸡进化史_乙级_1003“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。得到“答案正确”的条件是: 1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或..._1003 pat乙级 最优
文章浏览阅读5.6k次。CH340与Android串口通信为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio移植的具体步骤CH340串口通信驱动函数通信过程中重难点还存在的问题为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio为了在这个工程基础上进行改动,验证串口的数据和配置串口的参数,我首先在Eclipse上配置了安卓开发环境,注意在配置环境是..._340串口小板 安卓给安卓发指令