Hadoop学习之路(八):MapReduce进阶案例之寻找社交共同好友

本文介绍如何利用MapReduce找出社交网络中的共同好友。通过两阶段MapReduce作业,首先将用户的好友关系转化为共同好友的线索,然后重组数据以找出所有共同好友。在Hadoop 2.6.0-cdh5.7.0环境下,使用Java实现并部署到集群,最终成功获取到共同好友列表。
摘要由CSDN通过智能技术生成

一、需求分析

  • 社交软件的盛行让我们的生活越来越便捷,我们经常使用社交软件添加好友,即每个人会有自己的好友列表。如果用字母表示人,字母与字母之间连线表示这两个人互为好友关系,那么部分社交关系图可能是这样的:
    在这里插入图片描述
    然而现实中的社交关系远比这个复杂得多,有时候,我们需要知道人与人之间的共同好友,这个是一个非常有价值的信息,因为可以根据此信息为用户推荐好友。所谓共同好友,就是指每两个人之间的共同好友。例如在图中,A与B他们都认识E,所以A与B存在一个共同好友E,现在要求出所有人,两两之间的所有共同好友。
  • 现在对问题进行抽象处理,使用如下格式表示关系,如就图中而言,A->C,E,K代表了A与C,E,K互为好友关系,现在给定一批这样的数据,然后编写MapReduce代码寻找两两之间的共同好友,就图中A和B两个人而言,输出结果是这样的:A-B C,E,K表示A和B两个有共同好友 C,E,K。

二、算法分析

  • 第一阶段的MapReduce作业,原数据如下:
    A->Q,I,Y,U,P
    B->Y,I,E,X,H,T
    C->I,W,O,U,Y,H,G
    
    给定类似于这种数据,求解共同好友,由图中我们发现,两个人即使互不认识,他们也可能有共同好友,所以分析问题的时候不能顺着去思考,可以这样思考,如果存在一个人E是两个人A和B的共同好友,那么反过来,对于E而言,他肯定存在两个好友A和B,这是确定的,所以我们第一步先将 A->Q,I,Y,U,P映射为(Q,A),(I,A),(Y,A),(U,A),(P,A),把每一行都进行这样映射之后,对Key聚合,Value用逗号进行隔开,得到这样的结果:(I,“A,B,C”),可以知道,A,B,C三个人都存在共同好友I。作业的第一阶段完成。
  • 第二阶段的MapReduce作业:
    第一阶段的MapReduce作业得到类似于(I,“A,B,C”)这样的元组之后,将其作为数据源输入。首先将Value拆分,然后通过组合,输出(A-B,I),(A-C,I),(B-C,I),意思是A和B存在一个共同好友I,以此为Key,进行聚合,Value用逗号隔开,就得到了我们想要的结果。值得注意的是:对于第一阶段聚合的元组,我们对其Value进行拆分重组是按照顺从第一个字母与第二个字母组合,然后第一个字母与第三个字母组合…,这样可能存在这样的Key:A-B,B-A,这两者显示是代表同一组关系,但是可能因为Value的里的顺序不一致导致重组不一样,所以,需要对拆分后的Value排序后再重组

三、编写代码

1.构建Java工程,引入Maven支持
  • 使用的Hadoop版本是 2.6.0-cdh5.7.0,开发工具是IEDA2018
  • 完整的Maven依赖如下
    <properties>
    <hadoop.version>2.6.0-cdh5.7.0</hadoop.version>
    </properties>
    
    <repositories>
    <repository>
     <id>cloudera</id>
     <url>https://repository.cloudera.com/artifactory/cloudera-repos</url>
    </repository>
    </repositories>
    
    <dependencies>
    <dependency>
     <groupId>org.apache.hadoop</groupId>
     <artifactId>hadoop-client</artifactId>
     <version>${
         hadoop.version}</version>
    </dependency>
    
    <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.11</version>
    </dependency>
    </dependencies>
    
2.编写第一阶段MapReduce作业代码
  • 创建并编写MapStepOne类,代码如下:
        /**
       * 求解社交共同好友第一阶段map
       */
      public class MapStepOne extends Mapper<LongWritable, Text,Text,Text> {
         
      
          @Override
          protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
         
              //获得文本
              String line = value.toString();
              //获得本人
              String person = line.split("->")[0];
              //获得朋友
              String[] friends = line.split("->")[1].split(",");
              //将朋友作为Key,本人作为Value
              for(String friend : friends){
         
                  context.write(new Text(friend),new Text(person));
              }
          }
      }
    
  • 创建并编写ReduceStepOne类,代码如下:
        	/**
       * 求解社交共同好友第一阶段reduce
       */
      public class ReduceStepOne extends Reducer<Text,Text,Text,Text> {
         
      
          @Override
          protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
         
              //聚合friend
              String persons = "";
              for (Text friend : values){
         
                  persons += friend.toString() + ",";
              }
              //将最后的逗号去除
              persons = persons.
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值