MapReducer-找共同好友

package com.billstudy.mr.friends;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.jobcontrol.ControlledJob;
import org.apache.hadoop.mapreduce.lib.jobcontrol.JobControl;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * 找朋友
 *  共同好友
	原始数据:每个人的好友列表
	A:B,C,D,F,E,O
	B:A,C,E,K
	C:F,A,D,I
	D:A,E,F,L
	E:B,C,D,M,L
	F:A,B,C,D,E,O,M
	G:A,C,D,E,F
	H:A,C,D,E,O
	I:A,O
	J:B,O
	K:A,C,D
	L:D,E,F
	M:E,F,G
	O:A,H,I,J
	……

	输出结果:每个人和其他各人所拥有的功能好友
	A-B	C,E,
	A-C	D,F,
	A-D	E,F,
	A-E	B,C,D,
	A-F	B,C,D,E,O,
	A-G	C,D,E,F,
	A-H	C,D,E,O,
	A-I	O,
	A-J	B,O,
	A-K	C,D,
	A-L	D,E,F,
	A-M	E,F,
	B-C	A,
	B-D	A,E,
	……
 * @author Bill
 * @since V1.0 2015年6月24日 - 下午4:53:01
 */
public class ShareFriends {

	/**
	 *
	 * 把拥有同一个朋友的放到同一组
	 *
	 * 将
	 *  A:B,C,D,F,E,O
	 *
	 * 输出:
	 * B	A
	 * C	A
	 * D	A
	 * F	A
	 * ....
	 *
	 * @author Bill
	 * @since V1.0 2015年6月24日 - 下午5:15:21
	 */
	static class Mapper1 extends Mapper<LongWritable, Text, Text, Text> {

		private final Text k = new Text();

		private final Text v = new Text();

		@Override
		protected void map(LongWritable key, Text value,Context context)
				throws IOException, InterruptedException {

			String[] persons = value.toString().split(":");

			if(persons.length != 2){
				return;
			}

			// 切分字段
			String self = persons[0];
			String[] friends = persons[1].split(",");

			v.set(self);
			for (int i = 0; i < friends.length; i++) {
				k.set(friends[i]);
				context.write(k, v);
			}
		}
	}

	/**
	 *
	 * 把拥有同一个朋友的拼接到一起,输出
	 *
	 * 将
	 * A	{B,C,D}
	 *
	 * 输出:
	 * A	B-C-D
	 * @author Bill
	 * @since V1.0 2015年6月24日 - 下午5:14:26
	 */
	static class Reducer1 extends Reducer<Text, Text, Text, Text>{

		// private final Text k = new Text();

		private final Text v = new Text();

		@Override
		protected void reduce(Text key, Iterable<Text> friends, Context context)
				throws IOException, InterruptedException {

			StringBuilder friendNames = new StringBuilder();

			for (Text friend : friends) {
				friendNames.append(friend.toString() + "-");
			}

			// 去掉最后一个杠杠
			v.set(friendNames.length() > 0 ? friendNames.substring(0, friendNames.length() - 1) : "" );

			context.write(key, v);

		}
	}

	/**
	 * 将拥有同一个朋友的人排序后两两拼接输出,让朋友任意的一对组合都可以分到同一组
	 *
	 * 将
	 * A	B-C-D-E-F
	 *
	 * 输出:
	 * B-C	A
	 * B-D	A
	 * B-E	A
	 * B-F	A
	 * C-D	A
	 * ....
	 * @author Bill
	 * @since V1.0 2015年6月24日 - 下午5:12:44
	 */
	static class Mapper2 extends Mapper<LongWritable, Text, Text, Text>{

		private final Text k = new Text();

		private final Text v = new Text();

		@Override
		protected void map(LongWritable key, Text value,Context context)
				throws IOException, InterruptedException {

			String[] persons = value.toString().split("\t");
			String self = persons[0];
			String[] friends = persons[1].split("-");

			// 此处必须要对其朋友排序,否则交叉输出时会导致A-B:D / B-A:F 的问题出现,实际上述两个key为同一组。应该为:A-B:D,F
			Arrays.sort(friends);

			v.set(self);

			// 交叉打印
			for (int i = 0; i < friends.length - 1; i++) {
				for (int j = i + 1; j < friends.length; j++) {
					 k.set(friends[i] + "-" + friends[j]);
					 context.write(k, v);
				}
			}
		}
	}

	/**
	 *
	 * 把分到同一组组合的朋友拼接输出
	 *
	 * 将类似:
	 * 	A-B B
	 *  A-B C
	 *  A-B D
	 *
	 * 输出:
	 * A-B	B,C,D
	 * @author Bill
	 * @since V1.0 2015年6月24日 - 下午5:11:24
	 */
	static class Reducer2 extends Reducer<Text,Text,Text,Text>{

		// private final Text k = new Text();

		private final Text v = new Text();

		@Override
		protected void reduce(Text pair, Iterable<Text> friends,Context context)
				throws IOException, InterruptedException {

			StringBuilder friendNames = new StringBuilder();

			for (Text friend : friends) {
				friendNames.append(friend.toString() + ",");
			}

			// 去掉逗号
			v.set(friendNames.length() > 0 ? friendNames.substring(0, friendNames.length() - 1) : "");

			context.write(pair, v);

		}

	}

	public static void main(String[] args) throws Exception {

		if (args.length != 3) {
			System.err.println("Usage:<job1-inpath> <job1-outPath> <job2-outPath>");
			System.exit(1);
		}

		Configuration conf = new Configuration();

		// 创建路径,清除旧数据
		Path job1InputPath = new Path(args[0]);
		Path job1OutputPath = new Path(args[1]);
		Path job2OutputPath = new Path(args[2]);

		FileSystem fs = FileSystem.get(conf);
		if (fs.exists(job1OutputPath)) {
			fs.delete(job1OutputPath, true);
		}

		if (fs.exists(job2OutputPath)) {
			fs.delete(job2OutputPath, true);
		}

		// job1
		Job job1 = Job.getInstance(conf);
		job1.setJarByClass(ShareFriends.class);
		job1.setMapperClass(Mapper1.class);
		job1.setReducerClass(Reducer1.class);

		job1.setOutputKeyClass(Text.class);
		job1.setOutputValueClass(Text.class);

		FileInputFormat.addInputPath(job1, job1InputPath);
		FileOutputFormat.setOutputPath(job1, job1OutputPath);

		// job2
		Job job2 = Job.getInstance(conf);
		job2.setJarByClass(ShareFriends.class);
		job2.setMapperClass(Mapper2.class);
		job2.setReducerClass(Reducer2.class);

		job2.setOutputKeyClass(Text.class);
		job2.setOutputValueClass(Text.class);

		FileInputFormat.addInputPath(job2, job1OutputPath);
		FileOutputFormat.setOutputPath(job2, job2OutputPath);

		// 控制依赖
		ControlledJob controlledJob1 = new ControlledJob(conf);
		ControlledJob controlledJob2 = new ControlledJob(conf);

		controlledJob1.setJob(job1);
		controlledJob2.setJob(job2);
		controlledJob2.addDependingJob(controlledJob1);

		JobControl jobControl = new JobControl("share-friends");
		jobControl.addJob(controlledJob1);
		jobControl.addJob(controlledJob2);

		// 创建线程,开始执行任务
		Thread shareFriendExecuteThread = new Thread(jobControl);
		shareFriendExecuteThread.start();

		while(!jobControl.allFinished()){
			TimeUnit.SECONDS.sleep(1);
		}

		jobControl.stop();

		//  弹出两个job的输出结果文件夹
		Runtime.getRuntime().exec("cmd.exe /c start " + job1OutputPath.toUri().getPath().substring(1));
		Runtime.getRuntime().exec("cmd.exe /c start " + job2OutputPath.toUri().getPath().substring(1));
	}

}
时间: 2024-10-13 08:20:38

MapReducer-找共同好友的相关文章

Mapreduce案例之找共同好友

数据准备: A:B,C,D,F,E,OB:A,C,E,KC:F,A,D,ID:A,E,F,LE:B,C,D,M,LF:A,B,C,D,E,O,MG:A,C,D,E,FH:A,C,D,E,OI:A,OJ:B,OK:A,C,DL:D,E,FM:E,F,GO:A,H,I,J 需求: 1.先求出A.B.C.….等是谁的好友 2.求出哪些人两两之间有共同好友,及他俩的共同好友都有谁? 需求解读: 1.有题目可得,该关系为单项关系可以理解为关注,即A关注的为BCDEF,B关注的为AK,所以求A B C...

灰色头像

引子 你灰色头像不会再跳动 哪怕是一句简单的问候 心贴心的交流一页页翻阅多难过 是什么 坠落 升空 又想起你曾说的陪我到最后 暖色的梦变冰凉的枷锁 如果时光倒流我们又能抓得住什么. 背景 WJMZBMR喜欢上QQ..但是很多人的头像已经变成灰色了.这让他压力很大.而且WJMZBMR的好友太多了,大量的灰色头像让他无法准确的找到他想找的好友.. 今天WJMZBMR决定清理一下他的QQ,找出那些不会在跳动的头像并且把它们踢掉.为此他翻出了最近一个月的聊天记录. 如果一个头像在在最近一个月中与WJMZ

情绪管理与控制

体察自己的情绪 你要时时提醒自己注意:"我现在的情绪是什么?"例如:当你因为朋友约会迟到而对他冷言冷语,问问自己:"我为什么这么做?我现在有什么感觉?"如果你察觉你已对朋友三番两次的迟到感到生气,你就可以对自己的生气做更好的处理.有许多人认为:"人不应该有情绪",所以不肯承认自己有负面的情绪,要知道,人一定会有情绪的,压抑情绪反而带来更不好的结果,学着体察自己的情绪,是情绪管理的第一步. 适当表达自己的情绪 再以朋友约会迟到的例子来看,你之所以生

MapReduce实战(六)

需求: 利用mapReduce实现类似微信好友中查找共同好友的功能.如下: A:B,C,D,F,E,OB:A,C,E,KC:F,A,D,ID:A,E,F,LE:B,C,D,M,LF:A,B,C,D,E,O,MG:A,C,D,E,FH:A,C,D,E,OI:A,OJ:B,OK:A,C,DL:D,E,FM:E,F,GO:A,H,I,J 求出哪些人两两之间有共同好友,及他俩的共同好友都是谁.比如:A,B:[C,E] 分析: 在利用MapReduce程序解答之前,我们不妨用单机程序练习一下,思路很简单,

写在开发之外的一段小心事

世上本没有路,走的人多了,路也就没有了. 有时候记录开发过程中遇见的问题只是出于一种习惯,习惯了每天记录每天就会记录一点儿自己的心得,可以总会有那么一段时间觉得自己很忙,也就是给自己找一个机会或者理由去偷一偷懒,不是很忙,却假装很忙的样子,什么也没有记录.在别的孩子还在嬉笑追逐的时候,我学会了写日子,被迫每日一记,从最开始的一大段,几乎一页的日记,到最后的一小段,甚至成为后来的一句话,最后没有了那种约束也就从一句话到最后的停下来了.后来有一天突然重新拾起的时候,那时已经懂的了一些事情,并不是真正

关于微信公众平台开发TOKEN校验错误的问题

毕设做的差不多了,闲了几天,无事可做玩着微信,一时兴起想看看微信是如何开发的! 百度了一下,开发微信的基础要求会使用PHP,我想,我有web开发经验和android开发经验海派微信么? 要说PHP不会的话,什么都不用说!拿过来看一看,学一学,不就会了吗?再说了编程语言都是想通的,逻辑上都是一样的!本着这个想法,开始了我的微信平台开发之旅! 首先需要注册微信平台号,百度有教程 再者需要服务器,现有BAE(百度应用引擎)和SAE(新浪应用引擎),我用的是SAE因为很久很久之前就注册了账号,但一直没有

IOS UITableView性能优化

1.关于UITableView性能的优化,很容易就让人想起UITableView的复用,那么除此之外呢?还有么有其他的方法能够优化用户的体验,或者说优化我们的设计的软件呢? 答案是:有! 一般我们在设计一款应用的时候,占用系统资源最多,应该就是图片的加载了吧,的确,一方面图片占用的内存大,而且数量多,通常我们需要开启多个线程去下载这些图片,但是这些图片当中,有些图片用户是并不关心的,如何加载用户喜欢的资源(图片),而不去加载那些用户不感兴趣的资源,就是今天的主题,这个问题的解决方法,其实说出来估

第三次人机界面

最后一次人机界面设计,老师让做的是基于在手机上能显示网页的软件或者系统.这次题材是自己小组定的. 当时一开始我就想到做一个关于游戏的网页,结果也就这样做咯.然而这次也是最后一次,都是我完成的.因为真的,有w3school这个学习网站,好多实例可以应用,在加上自己找的一个资源.我也就自己一个人完成了,因为毕竟只有界面,我认为还是蛮简单的说.以下就来展示下这次效果和代码.注:来自网络的帮助肯定是有的,所以如果有哪位前辈看到自己的代码在这里的话,请见谅.我以此表达感谢.界面的演示是在手机模拟浏览器op

互联网点对点通讯(P2P)

摘自: http://www.cnblogs.com/zhili/archive/2012/09/14/p2p_pnpr.html [C# 网络编程系列]专题八:P2P编程 引言: 前面的介绍专题中有朋友向我留言说介绍下关于P2P相关的内容的,首先本人对于C#网络编程也不是什么大牛,因为能力的关系,也只能把自己的一些学习过程和自己的一些学习过程中的理解和大家分享下的,下面就进入正题——P2P(Peer to Peer)编程 一.P2P的介绍 首先,现在大家熟知的BT.电驴.迅雷.QQ.MSN和P

英国首相任命保守党党鞭威廉姆森为新国防大臣y

无噪洗衣机这个洗衣机的外形看起来非常的酷,不过这并不是它最特别的地方.最近6架美制"阿帕奇"直升机运抵台湾,每架售价约7000万美元,但美国卖给希腊的每架售价却只是5600万美元.迫于房价调控目标的压力,2013年第四季度以来,多个城市集体发力进行调控升级借壳概念股多数股价已高在疲惫的大盘走势中,借壳成为各路资金的追捧对象,并创造了一个个造富神话."有业内人士向记者表示,这样远洋若拓展融资,可以获得股东的支持,这可能也是远洋积极扩张的主要因素.基金份额持有人在权益登记日是否持