大数据Hadoop学习之——好友推荐_量化数据库 好友推荐-程序员宅基地

技术标签: 算法  好友推荐  mapreduce  hadoop  大数据  

一、算法说明

好友关系如图:

                                       

   1、直接相连的表示两个人是直接好友关系;

   2、两个人有相同的好友表示两个人是间接好友(当然可能两个人同时也是直接好友,如图hello和hive)。

   3、好友推荐列表就是按照两个用户的共同好友数量排名

 

二、MapReduce分析

1、分两步MapReduce计算完成;

2、第一步先得到用户的间接好友关系数目,注意有直接好友关系的用户需要过滤掉;

3、第二步根据间接好友关系数就可以得到用户推荐列表。

 

三、MapReduce实现

输入数据

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传送门

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xdkb159/article/details/108143622

智能推荐

html Canvas粒子文字特效_html canvas 效果-程序员宅基地

文章浏览阅读757次,点赞19次,收藏9次。文字动态特效_html canvas 效果

el-table-column 表格列自适应宽度的组件封装说明

针对组件业务上的需求,需要给 el-table-column 加上限制,需保证表头在一行展示,部分列的内容要一行展示,自适应单项列的宽度;

Ali-Sentinel-链路控制

Ali-Sentinel-链路控制

C语言实现SM4(基于GMSSL)_使用c语言调用openssl实现sm4代码-程序员宅基地

文章浏览阅读4.2k次。环境:vs2019 gmssl 32位编译1、首先新建项目2、在VS的工程设置工程属性(参考连接https://blog.csdn.net/zhonghua_csdn/article/details/99011892)右击工程名 ——> 选择“属性” 在“VC++目录”——> “包含目录”中添加openSSL的include文件(在您安装openssl的文件下) 在“VC++目录”——> “库目录”中添加openSSL的lib文件(在您安装openssl的文件下) 在“._使用c语言调用openssl实现sm4代码

让Windows免疫Autorun病毒-程序员宅基地

文章浏览阅读73次。来源:http://www.bysjhf.com.cn目前,U盘病毒的情况非常严重,几乎所有带病毒的U盘,根目录里都有一个autorun.inf。右键菜单多了“自动播放”、“Open”、“Browser”等项目。由于我们习惯用双击来打开磁盘,但现在我们双击,通常不是打开U盘,而是让autorun.inf里所设的程序自动播放。所以对于很多人来说相当麻烦。其实Autorun...._linux怎么为windows做autorun免疫

随便推点

Qt报错:Error while building/deploying project *** (kit: Desktop Qt 5.12.9 MSVC2017...)_error while building/deploying project xianzhazhi -程序员宅基地

文章浏览阅读1.5k次。Qt Creator 报错:Error while building/deploying project helloworld (kit: Desktop Qt 5.6.2 MinGW 32bit) When executing step "qmake" - zhangjunwu - 博客园 (cnblogs.com)https://www.cnblogs.com/zhangjunwu/p/7417566.html注意:Qt文件路径不要出现中文名字和空格!!!......_error while building/deploying project xianzhazhi (kit: desktop qt 5.12.9 ms

解决create-react-app创建项目出错_installing packages. this might take a couple of m-程序员宅基地

文章浏览阅读1.3k次。Installing packages. This might take a couple of minutes.Installing react, react-dom, and react-scripts with cra-template-typescript...npm ERR! code 1npm ERR! path C:\Users\MHX\Desktop\react-demo\node_modules\canvasnpm ERR! command failednpm ERR! comm_installing packages. this might take a couple of minutes. installing react,

关于西电计科本科学习的一些经验分享与资料汇总_西电毕设拿良容易吗-程序员宅基地

文章浏览阅读1.9w次,点赞43次,收藏214次。关于西电计科本科学习的一些经验分享与资料汇总_西电毕设拿良容易吗

【nodejs】使用express-generator快速搭建项目框架-程序员宅基地

文章浏览阅读279次,点赞9次,收藏3次。项目根目录打开终端,执行以下命令,安装依赖。执行以下命令后,在浏览器中打开。就可以打开这个项目了。

c++二维vector_c++ 二维vector-程序员宅基地

文章浏览阅读8.5k次,点赞4次,收藏24次。关于C++中二维vector使用vector本来就是可以用来代替一维数组的,vector提供了operator[]函数,可以像数组一样的操作,而且还有边界检查,动态改变大小。这里只介绍用它来代替二维的数组,二维以上的可以依此类推。1、定义二维vectorvector<vector<int>> A;//错误的定义方式vector<vector<int> > A;//正缺的定义方式vector<vector<int> > v;/_c++ 二维vector

python算法题_python算法题-程序员宅基地

文章浏览阅读187次。广告关闭腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!导言:记录下学习的算法题,写练多,脑子才能转的快! 今日算法题:二分法查找说下我对于二分法查找的理解:【和猜数字游戏差不多】 要在一个有序数列中找到一个与对应给定数字。 1、找到有序数列中最中间的数字2、若中间值大于给定值,则在左边数列重新二分查找3、若中间值小于给定值,则在右边数列..._python服务端算法题