Spark API In Java8
一、map、flatMap
map十分容易理解,他是將源JavaRDD的一個一個元素的傳入call方法,並經過算法後一個一個的返回從而生成一個新的JavaRDD。
map
- 示例代碼
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(list.size());
JavaRDD<Integer> listRDD = sc.parallelize(list);
JavaRDD<Integer> nameRDD = listRDD.map(n -> {
return n * n;
});
nameRDD.foreach(f -> {
System.out.println("n的平方=" + f);
});
- 運行結果
n的平方=1
n的平方=4
n的平方=9
可以看出,對於map算子,源JavaRDD的每個元素都會進行計算,由於是依次進行傳參,所以他是有序的,新RDD的元素順序與源RDD是相同的。而由有序又引出接下來的flatMap。
flatMap
flatMap與map一樣,是將RDD中的元素依次的傳入call方法,他比map多的功能是能在任何一個傳入call方法的元素後面添加任意多元素,而能達到這一點,正是因爲其進行傳參是依次進行的。
- 示例代碼
List<String> list = Arrays.asList("張無忌 趙敏","宋青書 周芷若");
JavaRDD<String> listRDD = sc.parallelize(list);
JavaRDD<String> nameRDD = listRDD
.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String line) throws Exception {
return Arrays.asList(line.split(" ")).iterator();
}
});
nameRDD.foreach(s-> {
System.out.println("Hello "+s);
});
- 運行結果
Hello 張無忌
Hello 趙敏
Hello 宋青書
Hello 周芷若
二、reduce、reduceByKey
reduce
reduce其實是講RDD中的所有元素進行合併,當運行call方法時,會傳入兩個參數,在call方法中將兩個參數合併後返回,而這個返回值回合一個新的RDD中的元素再次傳入call方法中,繼續合併,直到合併到只剩下一個元素時。
- 示例代碼
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
JavaRDD<Integer> listRDD = sc.parallelize(list);
Integer result = listRDD.reduce((x, y) -> x + y);
System.out.println(result);
}
- 運行結果
21
reduceByKey
reduceByKey僅將RDD中所有K,V對中K值相同的V進行合併
- 示例代碼
List<Tuple2<String, Integer>> list = Arrays.asList(
new Tuple2<String, Integer>("武當", 99),
new Tuple2<String, Integer>("少林", 97),
new Tuple2<String, Integer>("武當", 89),
new Tuple2<String, Integer>("少林", 77)
);
JavaPairRDD<String, Integer> listRDD = sc.parallelizePairs(list);
//運行reduceByKey時,會將key值相同的組合在一起做call方法中的操作
JavaPairRDD<String, Integer> result = listRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer i1, Integer i2) throws Exception {
return i1 + i2;
}
});
result.foreach(tuple->{
System.out.println("門派: " + tuple._1 + "->" + tuple._2);
});
- 運行結果
門派: 少林->174
門派: 武當->188
三、union,join和groupByKey
union,join
當要將兩個RDD合併時,便要用到union和join,其中union只是簡單的將兩個RDD累加起來,可以看做List的addAll方法。就想List中一樣,當使用union及join時,必須保證兩個RDD的泛型是一致的。
- 示例代碼
final List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
final List<Integer> list2 = Arrays.asList(3, 4, 5, 6);
final JavaRDD<Integer> rdd1 = sc.parallelize(list1);
final JavaRDD<Integer> rdd2 = sc.parallelize(list2);
rdd1.union(rdd2).foreach(num -> System.out.println(num));
- 運行結果
1
2
3
4
10:08:48.974 [Executor task launch worker for task 0] INFO org.apache.spark.executor.Executor - Finished task 0.0 in stage 0.0 (TID 0). 751 bytes result sent to driver
10:08:48.977 [dispatcher-event-loop-2] INFO org.apache.spark.scheduler.TaskSetManager - Starting task 1.0 in stage 0.0 (TID 1, localhost, executor driver, partition 1, PROCESS_LOCAL, 4976 bytes)
10:08:48.977 [Executor task launch worker for task 1] INFO org.apache.spark.executor.Executor - Running task 1.0 in stage 0.0 (TID 1)
3
4
5
6
groupByKey
union只是將兩個RDD簡單的累加在一起,而join則不一樣,join類似於hadoop中的combin操作,只是少了排序這一段,再說join之前說說groupByKey,因爲join可以理解爲union與groupByKey的結合:groupBy是將RDD中的元素進行分組,組名是call方法中的返回值,而顧名思義groupByKey是將PairRDD中擁有相同key值得元素歸爲一組。即:
- 示例代碼
List<Tuple2<String,String>> list = Arrays.asList(
new Tuple2("武當", "張三丰"),
new Tuple2("峨眉", "滅絕師太"),
new Tuple2("武當", "宋青書"),
new Tuple2("峨眉", "周芷若")
);
JavaPairRDD<String, String> listRDD = sc.parallelizePairs(list);
JavaPairRDD<String, Iterable<String>> groupByKeyRDD = listRDD.groupByKey();
groupByKeyRDD.foreach(tuple -> {
String menpai = tuple._1;
Iterator<String> iterator = tuple._2.iterator();
String people = "";
while (iterator.hasNext()){
people = people + iterator.next()+" ";
}
System.out.println("門派:"+menpai + "人員:"+people);
});
- 運行結果
門派:峨眉人員:滅絕師太 周芷若
門派:武當人員:張三丰 宋青書
join
join是將兩個PairRDD合併,並將有相同key的元素分爲一組,可以理解爲groupByKey和Union的結合
- 示例代碼
final List<Tuple2<Integer, String>> names = Arrays.asList(
new Tuple2<Integer, String>(1, "東方不敗"),
new Tuple2<Integer, String>(2, "令狐沖"),
new Tuple2<Integer, String>(3, "林平之")
);
final List<Tuple2<Integer, Integer>> scores = Arrays.asList(
new Tuple2<Integer, Integer>(1, 99),
new Tuple2<Integer, Integer>(2, 98),
new Tuple2<Integer, Integer>(3, 97)
);
final JavaPairRDD<Integer, String> nemesrdd = sc.parallelizePairs(names);
final JavaPairRDD<Integer, Integer> scoresrdd = sc.parallelizePairs(scores);
final JavaPairRDD<Integer, Tuple2<String, Integer>> joinRDD = nemesrdd.join(scoresrdd);
joinRDD.foreach(tuple -> System.out.println("學號:"+tuple._1+" 姓名:"+tuple._2._1+" 成績:"+tuple._2._2));
}
- 運行結果
學號:1 姓名:東方不敗 成績:99
學號:3 姓名:林平之 成績:97
學號:2 姓名:令狐沖 成績:98
五、filter、distinct
filter
- 示例代碼
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
JavaRDD<Integer> listRDD = sc.parallelize(list);
JavaRDD<Integer> filterRDD = listRDD.filter(num -> num % 2 ==0);
filterRDD.foreach(num -> System.out.println("num=="+num ));
- 運行結果
num==2
num==4
num==6
num==8
distinct
- 示例代碼
List<Integer> list = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 5);
JavaRDD<Integer> listRDD = (JavaRDD<Integer>) sc.parallelize(list);
listRDD.distinct().foreach(num -> System.out.println(num));
- 運行結果
num==4
num==1
num==3
num==5
num==2