使用Hadoop寻找两两用户之间有共同好友但他们不是好友的用户

博客介绍了如何使用Hadoop在社会网络中找出两两用户有共同好友但彼此不是好友的情况。通过MapReduce程序,分析用户好友关系文件,找出特定用户对并输出。Map阶段类似问题2,Reduce阶段读取好友关系缓存文件,判断并输出结果。
摘要由CSDN通过智能技术生成

使用Hadoop寻找两两用户之间有共同好友但他们不是好友的用户

1.问题描述

假定有一个社会网络A,每一个顶点表示一位用户,每一条边表示连接的两位用户是好友。A=(V,G),其中V是用户的集合,G是边的集合,即好友的集合。用文件分别保存V和G的数据,示例如下。例如G文件中,“a,b”表示用户a和用户b是好友。

#V文件:
a
b
c
…
#G文件:
a,b
a,c
b,e
b,k
…

找出哪些用户两两之间有共同好友,但他俩不是好友,输出这些用户对的列表。例如:

b-c
……

2.思路

这个问题跟问题2有一些相似之处,不过该问题只是输出哪些用户两两之间有共同好友,但他俩不是好友。该问题的Map端代码可以与问题2一样,只需要在Reduce端以及main( )函数修改一下就可以了。
main( )函数只需要将G文件(好友集合)放到distributed cache file中,Reduce端重写的setup( )函数读取按行该缓存文件生成一个个字符串并将其添加到一个ArrayList链表中。重写的reduce( )函数处理经过了Map端和Reduce端的Shuffle过程处理生成的数据<key, value-list>。具体是判断之前的ArrayList链表中是否包含该key。如果不包含,就将值设为空,将key写到最终文件里中;包含则不做处理。

3.带注解的MapReduce程序

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
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.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class Friends {
	
	//Map处理逻辑具体代码
	public static class FriMap extends Mapper<Object, Text, Text, Text> {
		@Override
		protected void map(Object key, Text value, Mapper<Object, Text, Text, Text>.Context context)
				throws IOException, InterruptedException {
			//将读取的一行内容转为字符串
			String line = value.toString();
			//通过“:	”对字符串切割得到该用户
			String commonFriend = line.split(":	")[0];
			//通过“:	”对字符串切割得到该用户的好友列表之后再对好友列表切割得到该用户的好友数组
			String[] friendsArray = line.split(":	")[1].split(",");
			for (int i = 0; i < friendsArray.length - 1; i++) {
				for (int j = i + 1; j < friendsArray.length; j++) {
					//通过双重for循环按顺序取出该用户的所有两个好友组合
					String first = friendsArray[i];
					String second = friendsArray[j];
					String combineFriends = first + "-" + second;
					context.write(new Text(combineFriends), new Text(commonFriend));
				}
			}
		}
	}
	
	//Reduce处理逻辑具体代码
	public static class FriReduce extends Reducer<Text, Text, Text, NullWritable> {
		//创建一个ArrayList来保存G文件(好友集合)里面的好友关系
		ArrayList<String> removeFriends = new ArrayList<>();
		
		@Override
		protected void setup(Reducer<Text, Text, Text, NullWritable>.Context context) throws IOException, InterruptedException {
			super.setup(context);
			try {
				//将distributed cache file装入各个Map节点本地的内存数据joinData中
				Path [] cacheFiles = context.getLocalCacheFiles();
				if (cacheFiles != null && cacheFiles.length > 0) {
					String line;
					//用来保存第一个用户
					String friendOne = " ";
					//用来保存第二个用户
					String friendTwo = " ";
					BufferedReader joinReader = new BufferedReader(new FileReader(cacheFiles[0].getName()));
					try {
						while ((line = joinReader.readLine()) != null) {
							//对读取的数据行处理
							friendOne = line.split(",")[0];
							friendTwo = line.split(",")[1];
							//将这两个好友进行排序
							if(friendOne.charAt(0) > friendTwo.charAt(0)) {
								String temp = friendOne;
								friendOne = friendTwo;
								friendTwo = temp;
							}
							//两个用户拼接后添加进ArrayList集合中
							removeFriends.add(friendOne + "-" + friendTwo);
						}
					} finally {
						joinReader.close();
					}
				}
			} catch (IOException e) {
				System.err.println("Exception reading DistributedCache: " + e);
			}
		}
		
		@Override
		protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, NullWritable>.Context context)
				throws IOException, InterruptedException {
			/*
			 * 判断好友集合中是否包含这两个用户
			 * 如果不包含,则将value设置为空,将这两个用户写入文件中
			 * 否则不做处理
			 */
			if (!removeFriends.contains(key.toString())) {
				//context.write(key, new Text(""));
				context.write(key, NullWritable.get());
			}
		}
	}
	
	//main()方法
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
		Configuration conf = new Configuration();
		conf.set("fs.defaultFS", "hdfs://localhost:9000");
		String[] str = new String[] {"friends_output1/part-r-00000", "friends_output3"};
		String[] otherArgs = (new GenericOptionsParser(conf, str)).getRemainingArgs();
		if (otherArgs.length != 2) {
            System.err.println("Usage: Friends and duplicate removal <in> <out>");
            System.exit(2);
        }
		Job job = Job.getInstance(conf, "Friends_03");    //设置环境参数
		job.setJarByClass(Friends.class);    //设置整个程序的类名
		job.setMapperClass(Friends.FriMap.class);    //添加Mapper类
		job.setReducerClass(Friends.FriReduce.class);  //添加Reducer类
		job.setOutputKeyClass(Text.class);    //设置输出键的类型
		job.setOutputValueClass(Text.class);    //设置输出值的类型
		//将G文件(好友集合)放入distributed cache file中
		job.addCacheFile(new URI("friends_input/G.txt"));
		//设置输入目录
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		Path outputPath = new Path(otherArgs[1]);
		//输出目录已经存在就删除输出目录
		if(outputPath.getFileSystem(conf).exists(outputPath))
			outputPath.getFileSystem(conf).delete(outputPath, true);
		//设置输出目录
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0:1);
	}
}

用到的文件

问题1的输出文件(part-r-00000)

a:	b,c,e,g,k
b:	a,e,k
c:	a,d,g
d:	c
e:	a,b,g,k
f:	g,i
g:	a,c,e,f,i,k
h:	j,k
i:	f,g,j
j:	h,i,k
k:	a,b,e,g,h,j

输入文件位置:

friends_output1/part-r-00000

输出文件目录:

friends_output3

前面两个问题的链接:
问题1
问题2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值