小马马说MapReduce算法案例(1):二度人脉好友推荐
2015-08-06 23:23
405 查看
二度人脉好友推荐运用非常广泛,比如在一些主流的社交产品中就有可能认识的人这样的功能,一般来说可能认识的人是通过二度人脉搜索得到的,在传统的关系型数据库中,可以通过图的广度优先遍历算法实现,而且深度限定为2,然而在海量的数据中,这样的遍历成本太大,所以有必要利用MapReduce编程模型来并行化,本篇文章是二度好友推荐的mapreduce简单实现,难免会有不足和缺陷,希望大家能够指出,共同进步。
假如A和B是好友关系,B和C是好友关系,然而C和A不是好友关系,那么A和C是二度好友关系,他们可以通过B认识,B是中间人。我们定义一个符号“>”来代表follow,上面的例子可以这样表示
在社交网络任何一个活跃的用户U都存在对应的两个集合,一个是粉丝集合,一个是关注集合,以用户U作为中间联系的2度人脉对,是粉丝集合和关注集合的笛卡尔积。
于是在Map阶段,我们可以这样输出Map结果
在shuffle阶段,会自动合并相同key值的value
于是上面通过shuffle阶段,reduce的输入变成
所以在reduce阶段我们可以得到以Key为中间人的好友集合,其中粉丝集合的元素第一个字母是’<’,关注集合的元素第一个字母是’>’,分离这两个集合,并求他们的笛卡尔积,就可以得到二度人脉的关系对。
以下是Map和Reduce函数的核心代码:
测试输入:
测试输出:
Map核心代码
Reduce核心代码
原创文章,转载请说明出处
假如A和B是好友关系,B和C是好友关系,然而C和A不是好友关系,那么A和C是二度好友关系,他们可以通过B认识,B是中间人。我们定义一个符号“>”来代表follow,上面的例子可以这样表示
A>B B>C
在社交网络任何一个活跃的用户U都存在对应的两个集合,一个是粉丝集合,一个是关注集合,以用户U作为中间联系的2度人脉对,是粉丝集合和关注集合的笛卡尔积。
于是在Map阶段,我们可以这样输出Map结果
key:“A ”value:“>B”; key:“B ”value:“<A”; key:“B ”value:“>C”; key:“C ”value:“<B”;
在shuffle阶段,会自动合并相同key值的value
于是上面通过shuffle阶段,reduce的输入变成
"A":[">B"] "B":["<A",">C"] "C":["<B"]
所以在reduce阶段我们可以得到以Key为中间人的好友集合,其中粉丝集合的元素第一个字母是’<’,关注集合的元素第一个字母是’>’,分离这两个集合,并求他们的笛卡尔积,就可以得到二度人脉的关系对。
以下是Map和Reduce函数的核心代码:
测试输入:
liujia qian qian sha sha yuan
测试输出:
liujia sha qian yuan
Map核心代码
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context) throws IOException, InterruptedException { String[] vaString=value.toString().split("\t"); context.write(new Text(vaString[0]), new Text(">"+vaString[1])); context.write(new Text(vaString[1]), new Text("<"+vaString[0])); }
Reduce核心代码
protected void reduce(Text arg0, Iterable<Text> arg1, Reducer<Text, Text, Text, Text>.Context arg2) throws IOException, InterruptedException { List<String> fuser= new ArrayList<String>(); List<String> buser= new ArrayList<String>(); Iterator<Text> it= arg1.iterator(); while (it.hasNext()) { String item=it.next().toString(); if(item.charAt(0)=='>') { fuser.add(item.toString().substring(1)); } else { buser.add(item.toString().substring(1)); } } for(int i=0;i<buser.size();i++) { for(int j=0;j<fuser.size();j++) { arg2.write(new Text(buser.get(i)), new Text(fuser.get(j))); System.out.println(buser.get(i)+"->"+fuser.get(j)); } } }
原创文章,转载请说明出处
相关文章推荐
- 关于连续使用fork()到底产生多少个子进程问题的实践
- 百度地图JavaScript API开发叠加行政区划图
- 打印Ibatis最终的SQL语句
- (转)C语言中的EOF和feof()
- AngularJS
- ios学习(导航栏上两个简单的设置)
- SQL语句in求和
- Ubuntu搭建LAMP环境
- 弱大数定律和强大数定律
- 记一个神奇的WAS问题:sibuswsgw-sibuswsgw_console.jar invalid LOC header (bad signature)
- 终于在windows下挑战编译安卓 chromium成功
- Java Persistence with MyBatis 3(中文版) 第四章 使用注解配置SQL映射器
- 复刻曹操传项目开源
- centos 7 gerrit安装配置
- 记一个神奇的WAS问题:sibuswsgw-sibuswsgw_console.jar invalid LOC header (bad signature) 分类: WebSphere 2015-08-06 23:21 9人阅读 评论(0) 收藏
- 【python工具篇】virtualenv和virtualenvwrapper
- uva 10057 A mid-summer night’s dream 夏天晚上的梦
- burp suite使用(一) --- 抓包,截包,改包
- Hash索引和BTree索引
- mybatis中的变量#与$