Spark(Java)统计共同好友

楔子

最近了解Spark,感觉挺有意思,有一点遗憾是应用的例子书上介绍的比较少,看到了一个Spark统计好友的。《数据算法 Hadoop Spark大数据处理技巧》

概述

数据如下,{personId,好友1,好友2,好友,3……}

100,200 300 400 500 600
200,100 300 400
300,100 200 400 500
400,100 200 300
500,100 300
600,100

简单的说,A 第一行数据中,可以认为 用户100 ,和用户500,的好友最多是{200 300 400 500 600}. B 再从用户500的角度(第五行数据)出发,用户500和用户100,最多的好友是{100 300} 在使用集合求交集,得到 共同好友300

Spark方案


此处使用Spark的RDD编写map和reduce函数,用户的数据从文本中读取,格式是(P是某个人,{F1,F2,F...})是P的直接好友

解决步骤如下:

  1. 导入必要的接口
  2. 检查输入数据
  3. 创建一个JavaSparkContext对象
  4. 创建第一个javaRDD表示输入文件
  5. 将JavaRDD(String)映射到键值对,其中key=Tuple<u1,u2> ,value=好友列表
  6. 将(key=Tuple2<u1,u2>,value=List(friends))对归约为(key=Tuple2<u1,u2>,value=List<List(friends)>)
  7. 利用所有的List<List>的交集查找共同好友

demo

可以步步为营,一步步调试,查看输出结果,这样更加容易理解

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.PairFlatMapFunction;
import scala.Tuple2;
// google 集合工具,
import com.google.common.collect.Lists;
import com.zhuzi.utils.SparkUtils;
/**
 * @Title: FriendLook.java
 * @Package com.zhuzi.bookj.char08
 * @Description: TODO(查询共同好友)
 * @author 作者 grq
 * @version 创建时间:2018年11月27日 下午6:48:55
 *
 */
public class FriendLook {
	public static void main(String[] args) {

		friends();
	}

	static void friends() {
		// 数据文件路径
		String filePath = SparkUtils.getFilePath("data/j/char08_friend.txt");

		JavaSparkContext ctx = SparkUtils.getJavaSparkContext();

		// 步骤4 创建第一个javaRDD表示输入文件
		JavaRDD<String> records = ctx.textFile(filePath, 1);

		// 步骤5 应用映射器 此处是 faltMap而不是map
		JavaPairRDD<Tuple2<String, String>, Iterable<String>> pairs = records.flatMapToPair(new PairFlatMapFunction<String, Tuple2<String, String>, // KEY
				Iterable<String>// VALUES
				>() {
					private static final long serialVersionUID = 1L;

					@Override
					public Iterator<Tuple2<Tuple2<String, String>, Iterable<String>>> call(String t) throws Exception {
						String[] tokens = t.split(",");
						String personID = tokens[0];
						String[] friendsTokens = tokens[1].split(" ");

						if (friendsTokens.length == 1) {
							Tuple2<String, String> key = buildSortPair(personID, friendsTokens[0]);
							Tuple2<Tuple2<String, String>, Iterable<String>> tempResult = new Tuple2<Tuple2<String, String>, Iterable<String>>(key, new ArrayList<String>());
							return Arrays.asList(tempResult).iterator();
						}
						List<String> friends = Arrays.asList(friendsTokens);

						List<Tuple2<Tuple2<String, String>, Iterable<String>>> result = new ArrayList<Tuple2<Tuple2<String, String>, Iterable<String>>>();
						for (String f : friends) {
							Tuple2<String, String> key = buildSortPair(personID, f);
							Tuple2<Tuple2<String, String>, Iterable<String>> tuple2 = new Tuple2<Tuple2<String, String>, Iterable<String>>(key, friends);

							result.add(tuple2);
						}

						return result.iterator();
					}
				});

		// 步骤6 应用归约器

		JavaPairRDD<Tuple2<String, String>, Iterable<Iterable<String>>> groupByKey = pairs.groupByKey();

		for (Tuple2<Tuple2<String, String>, Iterable<Iterable<String>>> iterable_element : groupByKey.collect()) {
			System.out.println(iterable_element);
		}
		// ((100,600),[[200, 300, 400, 500, 600], []])
		// ((100,500),[[200, 300, 400, 500, 600], [100, 300]])
		// ((200,400),[[100, 300, 400], [100, 200, 300]])
		// ((200,300),[[100, 300, 400], [100, 200, 400, 500]])
		// ((300,400),[[100, 200, 400, 500], [100, 200, 300]])
		// ((100,200),[[200, 300, 400, 500, 600], [100, 300, 400]])
		// ((100,300),[[200, 300, 400, 500, 600], [100, 200, 400, 500]])
		// ((100,400),[[200, 300, 400, 500, 600], [100, 200, 300]])
		// ((300,500),[[100, 200, 400, 500], [100, 300]])
		// 步骤7 查找共同好友
		JavaPairRDD<Tuple2<String, String>, Iterable<String>> mapValues = groupByKey.mapValues(new Function<Iterable<Iterable<String>>, Iterable<String>>() {

			@Override
			public Iterable<String> call(Iterable<Iterable<String>> v1) throws Exception {
				// 此处只有2个集合,所有我直接求交集
				ArrayList<Iterable<String>> list = Lists.newArrayList(v1);
				ArrayList<String> aList = Lists.newArrayList(list.get(0));
				ArrayList<String> bList = Lists.newArrayList(list.get(1));
				aList.retainAll(bList);
				return aList;
			}
		});

		List<Tuple2<Tuple2<String, String>, Iterable<String>>> collect = mapValues.collect();
		for (Tuple2<Tuple2<String, String>, Iterable<String>> tuple2 : collect) {
			System.out.println(tuple2);
		}

		// ((100,600),[])
		// ((100,500),[300])
		// ((200,400),[100, 300])
		// ((200,300),[100, 400])
		// ((300,400),[100, 200])
		// ((100,200),[300, 400])
		// ((100,300),[200, 400, 500])
		// ((100,400),[200, 300])
		// ((300,500),[100])
	}

	/**
	 * 确保不会得到重复的对象
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	static Tuple2<String, String> buildSortPair(String a, String b) {
		return a.compareTo(b) > 0 ? new Tuple2<String, String>(b, a) : new Tuple2<String, String>(a, b);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值