1. 程式人生 > >求好友中互粉的好友對

求好友中互粉的好友對

好友列表:

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,而B裡面好友有A,那麼A跟B就是互為好友。

我們的Map過程:
將好友列表檔案的每一行資料都進行提取出來,提取成好友:

A:B,C,D,F,E,O

經過Map就變成:

<A-B,NULL>
<A-C,NULL>
<A-D,NULL>
<A-F,NULL>
<A-E,NULL>
<A-O,NULL>
B:A,C,E,K

經過Map就變成

<A-B.NULL>
<B-C,NULL>
<B-E,NULL>
<B-K,NULL>
static class EachFanMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
		Text k = new Text();
		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
				String line = value.toString();
				String user = line.split(":")[0];
				String[] friends = line.split(":")[1].split(",");
				for(int i = 0; i < friends.length; i++) {
					String friend = friends[i];
					/**
					 * 下面這個過程就是關鍵的過程,
					 * 第一行資料 : A:B,C,D,F,E,O
					 * 第二行資料  :B:A,C,E,K
					 * A裡面有B,B裡面有A
					 * 現在我們需要獲取這兩個
					 * 那麼我們在map的時候, user 跟 friend 進行組合往reduce輸出的時候,
					 * 我們組合的時候需要進行排序,  
					 * 第一行資料組合  A-B
					 * 第二行如果沒有排序 那麼就是  B-A
					 * 但是我們在reduce進行處理時,需要的是相同的key
					 * 那麼我們應該讓 A-B  與  B-A 變成同一個key往reduce輸出
					 * 這樣reduce才能根據相同的key進行數量的統計
					 * 當數量為2時,就代表,A-B出現了兩次,那麼這一對手機互相關注的。
					 */
					if(user.compareTo(friend) < 0) {
						k.set(user + "-" + friend);
						context.write(k, NullWritable.get());
					} else {
						k.set(friend + "-" + user);
						context.write(k, NullWritable.get());
					}
				}
		}
	}	

reduce

static class EachFanReducer extends Reducer<Text, NullWritable, Text, NullWritable> {
		@Override
		protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
			int count = 0;
			for(NullWritable nw : values) {
				count++;
			}
			/**
			 * 嚴格來說,這個count要麼為1 要麼為 2,當為2的時候,就說明是互粉
			 */
			if(count == 2) {
				context.write(key, NullWritable.get());
			}
		}
	}

程式碼
https://gitee.com/tanghongping/hadoopMapReduce/tree/master/src/com/thp/bigdata/eachFan