大数据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

智能推荐

Linux查看服务器硬件网卡cpu型号内存BIOS、主板型号信息_linux查看主板型号-程序员宅基地

文章浏览阅读1.4w次,点赞6次,收藏43次。Linux查看服务器硬件网卡cpu型号内存BIOS、主板型号信息,查看服务器硬件信息CPU,内存等_linux查看主板型号

easyUI的datebox赋值以及取值,赋值不生效问题_easyui datebox取值-程序员宅基地

文章浏览阅读2.7k次。easyUI的datebox设定值以及取值1、时间戳格式化2、把格式化后的时间放入datebox中1、时间戳格式化时间格式处理按照下面时间框图片中显示的格式进行处理function parsedate(value) { var date = new Date(value).format("yyyy-MM-dd"); return date;..._easyui datebox取值

集成学习总结(二)_论文复现temporal attention-gated model for robust sequ-程序员宅基地

文章浏览阅读218次。1:Baggig方法:思想:给定一个大小为n的训练集 D,Bagging算法从中均匀、有放回地选出 m个大小为 n' 的子集Di,作为新的训练集。在这 m个训练集上使用分类、回归等算法,则可得到 m个模型,再通过取平均值、取多数票等方法综合产生预测结果,即可得到Bagging的结果。2:Stacking方法:思想:将训练好的所有基模型对整个训练集进行预测,第j个基模型对第i个训练样本的预测值将作为..._论文复现temporal attention-gated model for robust sequence classification

MAC下SSL通讯问题、解决办法_mac:60ee5cf723b4-程序员宅基地

文章浏览阅读2.5k次。问题:请求https出现ssl通讯错误解决方法:1、创建cacert.pem文件,可直接拷贝以下代码段内容到cacert.pem中2、将文件放入指定文件夹中(文件夹可自定义,小编的默认目录为:/usr/local/etc/)3、修改php.ini文件,curl.cainfo = "/usr/local/etc/cacert.pem"4、重启PHP即可#### Bundle of CA Root Certificates#### Certificate data from Mo_mac:60ee5cf723b4

[BUUCTF]PWN——wustctf2020_getshell1/2_ctf 有system无bin/sh-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏3次。wustctf2020_getshell附件步骤:例行检查,32位程序,开启了NX保护本地试运行一下程序,看看大概的情况32位ida载入,习惯性的检索程序里的字符串,发现了后门函数shell_addr=0x804851Bmain函数开始看程序vulnerable函数buf参数存在溢出漏洞,正好溢出8位,让我们覆盖到retexp:from pwn import*r=remote('node3.buuoj.cn',29690)shell_addr=0x804851B_ctf 有system无bin/sh

PHP7安装pdo_mysql扩展-程序员宅基地

文章浏览阅读2.9k次。因为自己在编译安装php7.2.7的时候,没有留意pdo_mysql失败。但是重新编译安装php7.2.7需要和长时间。百度了下,linux 有个 autoconfyum install autoconf -y 打开php安装包路径找到pdo_mysql进入文件夹检查扩展包是否问题/datas/soft/php72/bin/phpize设置..._php7 安装 pdo_mysql error: unknown type name ‘my_bool’ my_bool *in_null;

随便推点

java中getinputstream_Java Connection.getInputStream方法代码示例-程序员宅基地

文章浏览阅读1.1k次。import sun.rmi.transport.Connection; //导入方法依赖的package包/类/*** handleMessages decodes transport operations and handles messages* appropriately. If an exception occurs during message handling,* the sock..._conn.getinputstream()

深入理解Android中的Drawable类_自定义的png图片为什么要放到drawable中android-程序员宅基地

文章浏览阅读1.5k次。Drawable对于Android开发工程师来说非常熟悉,最常用的用法是在drawable目录里放入png或其他格式的图片,然后在代码里就可以用resources访问到如:// 访问test图片资源getResources().getDrawable(R.drwable.test);这里不是要讲Drawable资源怎么使用,而是来看一下这个类实现的一些原理以及它相关的一些子类的实现原理。..._自定义的png图片为什么要放到drawable中android

【网格生成】Gmsh快速入门教程 --3.Gmsh API_gmsh的api配置-程序员宅基地

文章浏览阅读4.4k次。在前面两篇文章1、2中我们分别介绍了图形化界面和内置解析器geo脚本的使用方式。今天来介绍下Gmsh的第三种使用方式:使用Gmsh API将其集成到其他软件中。意义将网格生成器与求解器等软件对接形成整体框架。获取Gmsh API几种方式通过官网下载SDK http://www.gmsh.info/bin/Windows/gmsh-git-Windows64-sdk.zippip install --upgrade gmsh (Python)在编译时加上 cmake -DENABLE_BUILD_gmsh的api配置

Ubuntu的复制粘贴操作及常用快捷键_ubuntu copy kuai jie jian-程序员宅基地

文章浏览阅读9w次,点赞22次,收藏107次。Ubuntu的复制粘贴操作 1.最为简单,最为常用的应该是鼠标右键操作了,可以选中文件,字符等,右键鼠标,复制,到目的地右键鼠标,粘贴就结束了。2.快捷键。一般通用的是Ctrl+C与Ctrl+V。不过通用也是有限制的,一般的程序下是没有问题,遇到终端就不行了。其实终端下默认的是 Ctrl+Shift+C,Ctrl+Shift+V,可以自己在编辑项下面自己设置为常用的。3.文件_ubuntu copy kuai jie jian

基于Springboot的宠物医院管理系统-JAVA【毕业设计、论文、源码、开题报告】_基于springboot的宠物医院管理系统国内外研究现状-程序员宅基地

文章浏览阅读5.8k次,点赞8次,收藏92次。1 绪论1.1 课题背景在信息技术高速发展的今天,新知识、新技术层出不穷,计算机技术早已广泛的应用于各行各业之中,利用计算机的强大数据处理能力和辅助决策能力叫,实现行业管理的规范化、标准化、效率化。管理信息系统(Management Information System,简称MIS〉是一个以人为主导,利用计算机软硬件技术以及网络通信技术,实现对信息的收集、传输、储存、更新。目前,管理信息系统广泛采用WEB技术作为开发的主要技术。在经过多年的技术积累与更新,WEB技术已经从一种简单的信息浏览和信息交互平台发展_基于springboot的宠物医院管理系统国内外研究现状

C++多线程:condition_variable_c++ condition_variable-程序员宅基地

文章浏览阅读2.6k次,点赞5次,收藏26次。官方定义在多线程编程中,有一种十分常见的行为:线程同步。线程同步是指线程间需要按照预定的先后次序顺序进行的行为。C++11对这种行为也提供了有力的支持,这就是条件变量(condition_variable和condition_variable_any)。条件变量位于头文件condition_variable下。condition_variable/condition_variable_any类是一个synchronization primitive,可用于阻止一个线程或同时阻止多个线程,直到另一个线程修改共_c++ condition_variable

推荐文章

热门文章

相关标签