前言
由于Scala语言编写Spark应用程序的便捷性。之前的案例操作都是用的Scala语言。但是由于大部分人都是学的Java,这里我使用Java编写了一个简单的Spark应用程序。如有不足,敬请指正!!!
数据介绍
输入数据如下所示:
hello hadoop cat
world hadoop hello hive
cat tom hive
mr hive hello
hive cat hadoop world hello mr
hadoop tom hive world
hello tom world hive mr
下面我解释一下上面数据的含义。就拿第二行来说:这个人叫world,他有三个好友,分别是:hadoop、hello和hive。hadoop、hello和hive之间就是间接好友。
在经历下面的程序之后,输出的数据如下:
mr_cat:1
world_tom:2
tom_hive:3
hello_hadoop:3
tom_mr:1
mr_hadoop:1
hello_cat:2
hadoop_cat:2
world_cat:1
world_mr:2
程序介绍
在上面的介绍中,我们知道了什么是直接好友与间接好友。在A的关系中,C和D是间接好友,在B的关系中,C和D也可能是间接好友。所以我们这个程序就是求出这种间接好友的数量。这对间接好友关系出现的次数越多、频率越高。这对间接好友就越有价值。
注意:A和B是间接好友的话,B和A也是间接好友,这两对间接好友对我们来说都是一样的意思,可是却分开进行统计,这样的结果显然不是我们想要的。
为了解决这个问题,我设计了一个String字符串拼接。如果A和B是间接好友,就根据某个规则来设计为:A_B。详情如下代码:
public static String addStr(String str1,String str2){
if(str1.compareTo(str2) >= 0){
return str1 + "_" + str2;
}else{
return str2 + "_" + str1;
}
}
代码区
package com.hpe.spark.instane;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.spark.SparkConf;
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.PairFlatMapFunction;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;
import scala.Tuple2;
public class Fof {
public static void main(String[] args) {
SparkConf conf = new SparkConf();
conf.setMaster("local");
conf.setAppName("Fof");
//在java中声明应用上下文
@SuppressWarnings("resource")
JavaSparkContext jsc = new JavaSparkContext(conf);
jsc.setLogLevel("WARN");
//获取初始RDD
JavaRDD<String> rdd = jsc.textFile("d:/data/friend.txt");
//分词,直接好友计数为0,间接好友计数为1
JavaPairRDD<String, Integer> flatMapToPairRDD = rdd.flatMapToPair(new PairFlatMapFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Iterable<Tuple2<String, Integer>> call(String input)
throws Exception {
List<Tuple2<String, Integer>> list = new ArrayList<Tuple2<String, Integer>>();
String[] words = input.split("\t");
String me = words[0];
for (int i=1 ; i<words.length ; i++ ) {
list.add(new Tuple2<String, Integer>(addStr(me,words[i]), 0));
for(int j=i+1 ; j<words.length ; j++){
list.add(new Tuple2<String, Integer>(addStr(words[j],words[i]), 1));
}
}
return list;
}
});
//分组
JavaPairRDD<String, Iterable<Integer>> groupByKeyRDD = flatMapToPairRDD.groupByKey();
//同一组内的数据若有直接好友关系,整组删除。否则计数累加
JavaPairRDD<String, Integer> javaPairRDD = groupByKeyRDD.mapToPair(new PairFunction<Tuple2<String,Iterable<Integer>>, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(
Tuple2<String, Iterable<Integer>> values) throws Exception {
boolean bool = false;
int count = 0;
String name = values._1;
Iterable<Integer> flags = values._2;
//统计间接好友出现的次数
for (Integer flag : flags) {
if(flag == 0){
bool = true;
}
count++;
}
//如果不是直接好友,就是间接好友,只返回间接好友
if(bool == false){
return new Tuple2<String, Integer>(name, count);
} else{
return new Tuple2<String, Integer>("直接好友", 0);
}
}
});
//输出
javaPairRDD.foreach(new VoidFunction<Tuple2<String,Integer>>() {
private static final long serialVersionUID = 1L;
@Override
public void call(Tuple2<String, Integer> friend) throws Exception {
if(friend._2 != 0){
System.out.println(friend._1 + ":" + friend._2);
}
}
});
//释放资源
jsc.stop();
}
//拼接字符串
public static String addStr(String str1,String str2){
if(str1.compareTo(str2) >= 0){
return str1 + "_" + str2;
}else{
return str2 + "_" + str1;
}
}
}