MapReduce实例——好友推荐

2023-05-16

1. 实例介绍

好友推荐算法在实际的社交环境中应用较多,比如qq软件中的“你可能认识的好友”或者是Facebook中的好友推介。好友推荐功能简单的说是这样一个需求,预测某两个人是否认识,并推荐为好友,并且某两个非好友的用户,他们的共同好友越多,那么他们越可能认识。

2. 数据流程

在这里插入图片描述

3. 具体实现

3.1 上传数据qq.txt

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

每个名字之间用”\t”分隔符隔开,第一个是用户,之后是好友列表。

3.2 代码编写

3.2.1 类型定义

由于A1:A2与A2:A1是同一个潜在好友列表,为了能够方便的统计,故统一按照字典排序,输出A1:A2格式。

public class FoF extends Text {
	
	public  FoF() {
		super();
	}
	
	public FoF(String friend01,String friend02) {
		set(getof(friend01,friend02));
	}

	private String getof(String friend01, String friend02) {
		
		int c = friend01.compareTo(friend02);
		if (c>0) {
			return friend02+"\t"+friend01;
		} 
		return friend01+"\t"+friend02;
	}
}

3.2.2 定义Map01

/**
 * map函数,统计好友之间的FOF关系列表(FOF关系:潜在好友关系)
 * @author JankoWilliam
 *
 */
public class Map01 extends Mapper<LongWritable, Text, FoF, IntWritable> {
	
	@Override
	protected void map(LongWritable key, Text value,Context context)
			throws IOException, InterruptedException {
		String lines = value.toString(); // 用户所有的好友列表
		String friends[] = StringUtils.split(lines, '\t');
		//好友之间的FOF关系矩阵
		for (int i = 1; i < friends.length; i++) {
			String friend = friends[i];
			context.write(new FoF(friends[0],friend),new IntWritable(0));//输出好友列表,值为0。方便在reduce阶段去除已经是好友的FOF关系。
			
			for (int j = i+1; j < friends.length; j++) {
				String friend2 = friends[j];
				context.write(new FoF(friend, friend2), new IntWritable(1));//输出好友之间的FOF关系列表,值为1,方便reduce阶段累加
			}
		}		
	}	
}

3.2.2 定义Reduce01

/**
 * reduce函数,统计全部的FOF关系列表的系数
 * @author JankoWilliam
 *
 */
public class Reduce01 extends Reducer<FoF, IntWritable,Text, NullWritable> {
	
	@Override
	protected void reduce(FoF key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
	
		int sum = 0;
		boolean f = true;
		for(IntWritable i : values){
			if (0==i.get()) { //已经是好友关系
				f=false;
				break;
			}
			sum+=i.get();	//累计,统计FOF的系数
		}
		System.out.println("******************Reduce01*******************");
		if (f) {
			String msg = StringUtils.split(key.toString(), '\t')[0]+" "+StringUtils.split(key.toString(), '\t')[1]+" "+sum;
			System.out.println(msg);
			context.write(new Text(msg), NullWritable.get()); //输出key为潜在好友对,值为出现的次数
		}
	}
}

3.2.3 定义 Job类

	public static void main(String[] args) {
		Boolean flag = jobOne();
	}
	// MapReduce01
	private static Boolean jobOne() {
		Configuration config = new Configuration();
		config.set("fs.defaultFS", "hdfs://node01:8020");
		config.set("yarn.resourcemanager.hostname", "node02:8088");
		
		boolean flag = false;
		try{
			Job job = Job.getInstance(config);
			
			job.setJarByClass(JobFriends.class);
			job.setJobName("fof one job");
			
			job.setMapperClass(Map01.class);
			job.setReducerClass(Reduce01.class);
			
			job.setOutputKeyClass(FoF.class);
			job.setOutputValueClass(IntWritable.class);
			
			FileInputFormat.addInputPath(job,new Path("/friend/input/qq.txt"));
			
			Path output = new Path("/friend/output/01");
			FileSystem fs = FileSystem.get(config);
			
			if (fs.exists(output)) {
				fs.delete(output,true);
			}
			FileOutputFormat.setOutputPath(job, output);
			
			flag = job.waitForCompletion(true);
			if (flag) {
				System.out.println("job1 success...");
			}
		} catch(Exception e){
			e.printStackTrace();
		} 
		
		return flag;
	}

输出结果:

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

3.2.4 好友推介计算,类型定义

由于在MapReduce中,key值自动能够排序,而value值往往不可以。所以为了根据每一个用户与其他用户的共同好友个数从高到低排序,不仅需要将用户名作为key,还需要将该用户与推介用户的共同好友个数作为key的一部分,所以需要重新定义一个类。

/**
 *  FriendSort作为key和value,FriendSort:用户名+FOF系数  
 *  用户名一致,FOF系数从大到小排序。 很容易得到一个用户的好友推介的列表
 * @author JankoWilliam
 *
 */
public class FriendSort implements WritableComparable<FriendSort>{
	
	private String friend;
	private int hot;
	
	public String getFriend() {
		return friend;
	}

	public void setFriend(String friend) {
		this.friend = friend;
	}

	public int getHot() {
		return hot;
	}

	public void setHot(int hot) {
		this.hot = hot;
	}
	

	public FriendSort() {
		super();
	}
	
	public FriendSort(String friend, int hot) {
		this.friend = friend;
		this.hot = hot;
	}
	//反序列化
	@Override
	public void readFields(DataInput in) throws IOException {
		this.friend=in.readUTF();
		this.hot=in.readInt();
	}
	//序列化
	@Override
	public void write(DataOutput out) throws IOException {
		out.writeUTF(friend);
		out.writeInt(hot);
	}
	//判断是否为同一用户,并通过hot值排序
	@Override
	public int compareTo(FriendSort newFriend) {
		System.out.println(friend+"-------"+newFriend.getFriend());

		int c = friend.compareTo(newFriend.getFriend());
		int e = -Integer.compare(hot, newFriend.getHot());
		if (c==0) {
			return e;
		}
		return c;
	}
}	

3.2.5 定义Map02

/**
 * map函数,每个用户的推介好友列表,并按推介指数从大到小排序
 * @author JankoWilliam
 *
 */
public class Map02 extends Mapper<LongWritable, Text, FriendSort, Text > {
	
	@Override
	protected void map(LongWritable key, Text value,Context context)
			throws IOException, InterruptedException {
		
		String lines = value.toString();	
		String friend01 = StringUtils.split(lines,' ')[0];
		String friend02 = StringUtils.split(lines,' ')[1];	//推介的好友
		int hot = Integer.parseInt(StringUtils.split(lines,' ')[2]);	// 该推介好友的推介系数
		
		System.out.println("**************Map02******************");
		System.out.println(friend01+"  "+friend02+"  "+hot);
		System.out.println(friend02+"  "+friend01+"  "+hot);
		context.write(new FriendSort(friend01,hot),new Text(friend02+":"+hot));	 //mapkey输出用户和好友推介系数
		context.write(new FriendSort(friend02,hot),new Text(friend01+":"+hot));	//好友关系是相互的
		
	}
}

3.2.6 定义sort类

/**
 * 将key根据用户名和次数排序
 * @author JankoWilliam
 *  
 */
public class NumSort extends WritableComparator{
	public NumSort(){
		super(FriendSort.class,true);
	}
	
	public int compare(WritableComparable a, WritableComparable b) {
		FriendSort o1 =(FriendSort) a;
		FriendSort o2 =(FriendSort) b;
		
		int r =o1.getFriend().compareTo(o2.getFriend());
		if(r==0){
			return -Integer.compare(o1.getHot(), o2.getHot());
		}
		return r;
	}
}

3.2.7 定义group类

	/**
	 *  将同一个用户作为一个Group,同时被reduce处理
	 * @author JankoWilliam
	 *
	 */
	public class UserGroup extends WritableComparator{
		public UserGroup(){
			super(FriendSort.class,true);
		}
		
		public int compare(WritableComparable a, WritableComparable b) {
			FriendSort o1 =(FriendSort) a;
			FriendSort o2 =(FriendSort) b;
			return o1.getFriend().compareTo(o2.getFriend());
		}
	}	

3.2.8 定义Reduce02

/**
 * reduce函数
 * @author JankoWilliam
 *
 */
public class Reduce02 extends Reducer<FriendSort, Text, Text, Text> {
	
	@Override
	protected void reduce(FriendSort user, Iterable<Text> friends,Context context)
			throws IOException, InterruptedException {
		
		String msg = "";
		//拼接推荐好友
		for(Text friend :friends){
			System.out.println("***************Reduce02*****************");
			msg += friend.toString()+",";
			System.out.println(msg);
		}
		context.write(new Text(user.getFriend()), new Text(msg));	
	}	
}

3.2.9 定义 Job类

public class JobFriends {
	
	public static void main(String[] args) {
		Boolean flag = jobOne();
		if (flag) {
			jobTwo();
		}
	}
	
	private static Boolean jobTwo() {  
		 Configuration config =new Configuration();
		 config.set("fs.defaultFS", "hdfs://node01:8020");
		 config.set("yarn.resourcemanager.hostname", "node02:8088");
		 
		 Boolean flag = false;
		 try {
			 Job job = Job.getInstance(config);
			 
			 job.setJarByClass(JobFriends.class);
			 job.setJobName("fof two job");
			 
			 job.setMapperClass(Map02.class);
			 job.setReducerClass(Reduce02.class);
			 job.setSortComparatorClass(NumSort.class); //sort类
			 job.setGroupingComparatorClass(UserGroup.class); //group类
			 job.setMapOutputKeyClass(FriendSort.class);
			 job.setMapOutputValueClass(Text.class);
			 
			 
			 FileInputFormat.addInputPath(job, new Path("/friend/output/01/"));
			 
			 Path output = new Path("/friend/output/02/");
			 
			 FileSystem fs = FileSystem.get(config);
			 if (fs.exists(output)) {
				 fs.delete(output, true);
			 }
			 
			 FileOutputFormat.setOutputPath(job, output);
			 
			 flag = job.waitForCompletion(true);
			 if (flag) {
				 System.out.println("job2 success...");
			 }
			 
		 } catch (Exception e) {
			 e.printStackTrace();
		 };
		 return flag;
	 }
}

输出结果,完成好友推荐列表:

cat		hello:2,hadoop:2,mr:1,world:1,
hadoop	hello:3,cat:2,mr:1,
hello	hadoop:3,cat:2,
hive	tom:3,
mr		world:2,hadoop:1,tom:1,cat:1,
tom		hive:3,world:2,mr:1,
world	mr:2,tom:2,cat:1,
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MapReduce实例——好友推荐 的相关文章

  • idea中Gradle项目控制台中文乱码

    我使用的是IEDA2021 xff0c 之前跑maven项目一切正常 今天导入了一个Gradle项目 xff0c debug的时候控制台中文乱码了 之前直接用idea控制台中文乱码做关键词搜索 xff0c 改了file settings e
  • @RequestMapping value值置为““

    我们通常用 64 RequestMapping来映射请求 xff0c 比如 xff0c 写一个方法 xff1a span class token annotation punctuation 64 RequestMapping span s
  • Android多媒体学习十:利用AudioRecord类实现自己的音频录制程序

    AudioRecord类相对于MediaRecorder来说 xff0c 更加接近底层 xff0c 为我们封装的方法也更少 然而实现一个AudioRecord的音频录制程序也很 简单 本实例代码如下 xff1a 可惜 xff0c 本实例测试
  • ROS系统SLAM基础学习:运行gazebo仿真建立保存地图

    ROS系统SLAM基础学习 xff1a gazebo仿真建立保存地图 使用gmapping建立并保存地图使用hector slam建立并保存地图遇到的问题解决以及总结 软件版本Ubuntu16 04LTSROSkineticgazebo7
  • 软件安装时窗口出现在屏幕左上角而且拖不出来

    今天在安装MYSQL是出现如下问题 xff1a 安装助手出现在屏幕左上角而且拖不出来 xff0c 导致安装没办法完成 用一个很简单的方法解决了问题 xff1a 桌面空白处右键 xff0c 点屏幕分辨率 把方向改成纵向 xff0c 左上角的窗
  • DELL笔记本插入耳机没反应

    新入的戴尔燃7000 xff0c 上午因为CPU占用飙升 xff0c 关掉了笔记本上的几个自启动项 xff0c 下午插入耳机就无响应了 xff0c 耳机插进去 xff0c 还是外放 百度原因 xff0c 很多都提及了Realtek这一声卡驱
  • the server responded with a status of 404 (Not Found)

    使用ajax跳转方法时 xff0c 页面ctrl 43 shift 43 i调试报告了一个404错误 xff0c 说找不到方法 页面地址栏直接指向方法的地址跳转也是404 目标方法是新增的 xff0c 于是使用复制黏贴 xff0c 确定各处
  • select设置只读

    根据需求 xff0c 需要根据后台传来的参数 xff0c 动态设置select标签是否可以选择 xff0c 因此 xff0c 当判断某个select应当设为只读时 xff0c 使用 span class hljs variable span
  • java:程序包XXXX不存在

    使用idea导入maven项目 xff0c 编译时报错 xff1a java 程序包XXXX不存在 如图 xff1a 百度到的诸如右键libraries所在文件夹 xff0c 选择add to libraries 等方法没有作用 后来去查看
  • tomcat启动报错:java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.Lifec

    tomcat启动报错 xff1a java lang IllegalStateException ContainerBase addChild start org apache catalina Lifec 百度的结果一般都是让修改web
  • UE4 音乐的播放与停止--基于蓝图

    要实现的功能非常简单 xff1a 点击按钮 xff0c 播放音乐 这个功能非常基础 xff0c 就两步 xff1a 1 将音乐源文件拖到context文件夹中 注意 xff0c 这里的音乐文件必须是 wav格式的 2 在按钮的onclick
  • UnityEditor.BuildPlayerWindow+BuildMethodException

    unity3D安卓打包报错 xff1a UnityEditor BuildPlayerWindow 43 BuildMethodException 61 errors at UnityEditor BuildPlayerWindow 43
  • AI 入门怎么学?这份学习指南请收好!

    万事开头难 xff01 AI 入门对很多初学 AI 的同学来说是一大难题 搜集了一大堆入门资料 xff0c Python 数学 深度学习应有尽有 xff0c 但就是无从下手 xff0c 总是在第一章与放弃之间徘徊 那么 xff0c AI 应
  • 为什么越厉害的大厂,校招越不看重考试成绩?

    前几天赵同学告诉我 xff0c 他没有通过那家心仪的公司笔试 赵同学成绩不错 xff0c 每次都是专业前五 xff0c 但笔试中有一道 银行家算法实现 题 xff0c 他一点也没写出来 这就是大厂招聘不看重成绩单的原因 xff1a 招人是为
  • 我的2011——毕业之年的总结与彷徨

    题记 眼看2011即将成为过去 xff0c 难得在这最后的时刻 xff0c 抽点时间 xff0c 倒上一杯热茶 xff0c 回忆这一年的浮浮沉沉 这一年 xff0c 我和所有毕业生一样 xff0c 离开了呆了四年的大学校园 呆腻了校园的生活
  • centos安装anaconda教程

    1 更新yum 命令 xff1a sudo yum update 2 安装anaconda 2 1 查看anaconda对应python版本 我选的3 8版 Old package lists Anaconda documentation
  • Android布局 -- Navigation实现底部导航栏

    底部导航栏加页卡的切换 xff0c 很多App采用这种布局设计 xff0c 在以前的开发中 xff0c 需要自定义底部导航栏以及使用FragmentTransaction来管理Fragment的切换 xff0c 代码量较大 xff0c 而使
  • ViewModelProviders is deprecated

    原有的创建ViewModel的方法 xff1a viewModel 61 ViewModelProviders of this get ViewModel class 提示ViewModelProviders过时 改为 xff1a view
  • Android Fragment退出 返回上一个Fragment与直接退出

    例如应用底部有两个导航按钮A与B xff0c 刚进入的时候显示为第一个AFragment xff0c 点击B切换到BFragment 如果需求是在BFragment点击返回键回到AFragment xff0c 需要配置 app defaul
  • Android基础 -- 子线程可以修改UI吗?

    子线程可以修改UI吗 xff1f 为什么会产生这样的问题 xff0c 可能是因为在开发过程中遇到了 34 Only the original thread that created a view hierarchy can touch it

随机推荐

  • leetcode 417. 太平洋大西洋水流问题

    https leetcode cn com problems pacific atlantic water flow 思路是从海洋开始逆流 如果可以逆流到 就标记为1 然后检查两个海洋都可以逆流到的区域 DFS public List lt
  • Android模拟器检测常用方法

    在Android开发过程中 xff0c 防作弊一直是老生常谈的问题 xff0c 而模拟器的检测往往是防作弊中的重要一环 xff0c 接下来有关于模拟器的检测方法 xff0c 和大家进行一个简单的分享 1 传统的检测方法 传统的检测方法主要是
  • RecyclerView 隐藏部分分割线

    在项目中遇到复杂点的RecyclerView xff0c 可能会有隐藏部分分割线的需求 xff0c 例如item1和item3之间的分割线隐藏 xff0c item4和item5之间的分割线隐藏等 在看了文档里的ItemDecoration
  • 浅谈去中心化应用

    1 中心化应用 现在我们所使用的应用基本上都是中心化的应用 xff0c 什么是中心化应用呢 xff0c 举个栗子 xff0c 我们在天猫买东西的时候 xff0c 需要先付款给支付宝 xff0c 然后卖家发货 xff0c 我们确认收货之后 x
  • Java二分搜索树及其添加删除遍历

    对于树这种结构 xff0c 相信大家一定耳熟能详 xff0c 二叉树 二分搜索树 AVL树 红黑树 线段树 Trie等等 xff0c 但是对于树的应用以及编写一棵解决特定问题的树 xff0c 不少同学都会觉得不是一件简单的事情 xff0c
  • 游戏平台SDK设计和开发之旅——XSDK功能点梳理

    做游戏开发或者相关工作的同学 xff0c 可能都知道 xff0c 在游戏上线之前 xff0c 需要将游戏分发到各大渠道平台 xff0c 比如九游 xff0c 百度 xff0c 360 xff0c 华为等等 其中和技术相关的事情 xff0c
  • 谈谈 GitHub 开放私有仓库一事的影响

    GitHub 此次宣布免费开放私有仓库 xff0c 在我看来有以下几点影响 xff1a 缓和与同类产品间的竞争压力小部分个人项目由开源转闭源微软在技术社区中的企业形象进一步强化为未来的企业服务预热 下面根据以上几点 xff0c 我来简单谈下
  • 每天坚持刷 LeetCode 的人,究竟会变得有多强... 学习技巧都藏在这几个公众号里面了......

    信息爆炸时代 xff0c 与其每天被各种看过就忘的内容占据时间 xff0c 不如看点真正对你有价值的信息 xff0c 下面小编为你推荐几个高价值的公众号 xff0c 它们提供的信息能真正提高你生活的质量 人工智能爱好者社区 专注人工智能 机
  • 超酷炫!智能无人机中文教程重磅上线!

    前 言 对于大多数无人机爱好者来说 xff0c 能自己从头开始组装一台无人机 xff0c 之后加入 AI 算法 xff0c 能够航拍 xff0c 可以目标跟踪 xff0c 是心中的梦想 并且 xff0c 亲自从零开始完成复杂系统 xff0c
  • B 站硬件大佬又在 GitHub 上开源了一款神器...

    公众号关注 GitHubDaily 设为 星标 xff0c 每天带你逛 GitHub xff01 转自量子位 这次 xff0c 野生钢铁侠稚晖君带着他的硬核项目又来了 上次自制纯手工打造 AI 小电视 xff0c 播放量就超过 300 万
  • 用 C 语言来刷 LeetCode,网友直呼:那是真的牛批...

    公众号关注 GitHubDaily 设为 星标 xff0c 每天带你逛 GitHub xff01 大家好 xff0c 我是小 G 如果你是计算机科班出身 xff0c 那么 C 语言 xff0c 估计是你在初入编程时 xff0c 最早接触的编
  • 【pytorch torchvision源码解读系列—3】Inception V3

    框架中有一个非常重要且好用的包 xff1a torchvision xff0c 顾名思义这个包主要是关于计算机视觉cv的 这个包主要由3个子包组成 xff0c 分别是 xff1a torchvision datasets torchvisi
  • 【pytorch torchvision源码解读系列—5】DenseNet

    pytorch框架中有一个非常重要且好用的包 xff1a torchvision xff0c 顾名思义这个包主要是关于计算机视觉cv的 这个包主要由3个子包组成 xff0c 分别是 xff1a torchvision datasets to
  • Eclipse使用JDBC方式连接SQLServer2016

    Eclipse使用JDBC方式连接SQLServer2016 今天下午在查找很多JDBC连接SQL时发现大多数都是2012甚至更久以前的版本 xff0c 所以就此把步骤记录下来 xff0c 以免自己下次使用又忘记了 在连接的时候 xff0c
  • 魔改《自动化学报》Latex模板

    想用latex写一个中文文档 xff0c 看上了 自动化学报 的模板 xff0c 感觉不错 xff0c 下载下来在本地的tex live上编译 xff0c 报了一大串错 xff1b 上传到overleaf xff0c 还是报错 xff1b
  • TX2安装jetpack

    目前官网支持的下载为JetPack L4T 3 2 1 linux x64 b23和JetPack L4T 3 3 linux x64 b39 首先使用具有Ubuntu16 04的host主机 xff08 我使用的是个人笔记本 xff0c
  • TF-IDF算法

    TF IDF算法 TF IDF term frequency inverse document frequency 是一种用于信息检索与数据挖掘的常用加权技术 xff0c 常用于挖掘文章中的关键词 xff0c 而且算法简单高效 xff0c
  • 大数据009——MapReduce

    分布式离线计算框架MapReduce MapReduce是一种编程模型 Hadoop MapReduce采用Master slave 结构 只要按照其编程规范 xff0c 只需要编写少量的业务逻辑代码即可实现一个强大的海量数据并发处理程序
  • MapReduce实例——wordcount(单词统计)

    1 MR实例开发整体流程 最简单的MapReduce应用程序至少包含 3 个部分 xff1a 一个 Map 函数 一个 Reduce 函数和一个 main 函数 在运行一个mapreduce计算任务时候 xff0c 任务过程被分为两个阶段
  • MapReduce实例——好友推荐

    1 实例介绍 好友推荐算法在实际的社交环境中应用较多 xff0c 比如qq软件中的 你可能认识的好友 或者是Facebook中的好友推介 好友推荐功能简单的说是这样一个需求 xff0c 预测某两个人是否认识 xff0c 并推荐为好友 xff