调研背景 :
本博主刚接触spark 开发,对其中的API 并不是特别的熟悉,对于以上提到的4种API 常分不清用法,故写下这篇文章作为参考。
如果有别的见解,希望踊跃留言 ~~~
主要的测试场景,模仿对语句中的单词进行切分~。(按照空格进行单词切分,词频统计的前一个步奏。
maven依赖:
org.apache.spark
spark-core_2.11
2.2.0
方法介绍
Map :(不推荐使用)
map函数会对每一条输入进行指定的操作,然后为每一条输入返回一个对象。
示例代码:
JavaRDD mapResult = linesRDD.map(new Function() {
@Override
public String[] call(String s) throws Exception {
return s.split(" ");
}
});
MapPartition :
MapPartition 函数会对每个分区中的一组数据进行相应的操作,并最终返回一个指定对象的迭代器。
建议使用 MapPartition 取代 Map 函数:
原因如下:
优点1:
对于 一些初始化操作,如果用map 函数可能需要对每一条数据都进行一次调用,而使用 MapPartition 可以一个分区只调用一次初始化操作,资源使用更高效!!
优点2:
通过mapPartition 可以非常方便的对返回结果进行过滤 (比如错误数据过滤),map 较难实现。
MapPartition 也可以完成 FlatMap 相类似的功能;(但是底部的实现原理可能并不相同),见后文
示例代码:
JavaRDD mapPartitionsResult = linesRDD.mapPartitions(new FlatMapFunction, String[]>() {
@Override
public Iterator call(Iterator stringIterator) throws Exception {
List resultArr = new ArrayList<>();
while (stringIterator.hasNext()) {
String line = stringIterator.next();
String[] tmpResult = line.split(" ");
resultArr.add(tmpResult);
}
return resultArr.iterator();
}
});
FlatMap:
flatMap函数则是两个操作的集合——正是“先映射后扁平化”:
操作1:同map函数一样:对每一条输入进行指定的操作,然后为每一条输入返回一个对象
操作2:最后将所有对象合并为一个对象
FlatMap 与 Map 的主要区别 :
Map 主要转换是一条数据 返回 一条数据
FlatMap 将一条数据转换为 一组数据 (迭代器),主要用于将一条记录转换为多条记录的场景,如对 每行文章中的单词进行切分,
返回 每行中所有单词。
示例代码:
JavaRDD flatMapResult = linesRDD.flatMap(new FlatMapFunction() {
@Override
public Iterator call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
其实:按照我的理解, MapPartition 也可以完成 FlatMap 相类似的功能;(但是底部的实现原理可能并不相同)
假设实现的功能是将语句按照 “ ”(空格)进行切分, 返回单词列表:
System.out.println("MapPartition simulate flatMap operation");
JavaRDD mapPartitionLikeFlatMapResult = linesRDD.mapPartitions(
new FlatMapFunction, String>() {
@Override
public Iterator call(Iterator stringIterator) throws Exception {
List resultList = new ArrayList<>();
while(stringIterator.hasNext()){
String tmpLine = stringIterator.next();
String[] tmpWords = tmpLine.split(" ");
for(String tmpString : tmpWords){
resultList.add(tmpString);
}
}
return resultList.iterator();
}
}
);
mapPartitionLikeFlatMapResult.foreach(new VoidFunction() {
@Override
public void call(String s) throws Exception {
System.out.println(s);
}
});
System.out.println("\n\n");
FlatMapToPair:
flatMapToPair 其实是在FlatMap 函数基础上将返回的数据转换为了 1个Tuple, 即 key-value 格式的数据。方便相同的key 的数据进行后续的统计如统计次数等操作。
示例代码:
JavaPairRDD flatMapToPairResult = linesRDD.flatMapToPair(
new PairFlatMapFunction() {
@Override
public Iterator> call(String s) throws Exception {
List> resultTuple = new ArrayList<>();
String[] tmpList = s.split(" ");
for (String tmpString : tmpList) {
resultTuple.add(new Tuple2<>(tmpString, 1));
}
return resultTuple.iterator();
}
});
整体的示例代码:
package com.spark.test.batch.job;
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.FlatMapFunction;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.PairFlatMapFunction;
import org.apache.spark.api.java.function.VoidFunction;
import scala.Tuple2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Created by szh on 2018/5/2.
*
* @author szh
* @date 2018/5/2
*/
public class MultiMapCompare {
public static void main(String[] args) {
SparkConf sparkConf = new SparkConf();
sparkConf.setAppName("MultiMapCompare").setMaster("local[2]");
JavaSparkContext sparkContext = new JavaSparkContext(sparkConf);
sparkContext.setLogLevel("ERROR");
List linesList = new ArrayList<>();
linesList.add("You are a bad man");
linesList.add("Just a test job");
JavaRDD linesRDD = sparkContext.parallelize(linesList);
System.out.println("map Result");
JavaRDD mapResult = linesRDD.map(new Function() {
@Override
public String[] call(String s) throws Exception {
return s.split(" ");
}
});
mapResult.foreach(new VoidFunction() {
@Override
public void call(String[] strings) throws Exception {
for (String tmp : strings) {
System.out.println(tmp);
}
}
});
System.out.println("\n\n");
System.out.println("mapPartitions Result");
JavaRDD mapPartitionsResult = linesRDD.mapPartitions(new FlatMapFunction, String[]>() {
@Override
public Iterator call(Iterator stringIterator) throws Exception {
List resultArr = new ArrayList<>();
while (stringIterator.hasNext()) {
String line = stringIterator.next();
String[] tmpResult = line.split(" ");
resultArr.add(tmpResult);
}
return resultArr.iterator();
}
});
mapPartitionsResult.foreach(new VoidFunction() {
@Override
public void call(String[] strings) throws Exception {
for (String tmp : strings) {
System.out.println(tmp);
}
}
});
System.out.println("\n\n");
System.out.println("flatMap Result");
JavaRDD flatMapResult = linesRDD.flatMap(new FlatMapFunction() {
@Override
public Iterator call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
flatMapResult.foreach(new VoidFunction() {
@Override
public void call(String s) throws Exception {
System.out.println(s);
}
});
System.out.println("\n\n");
System.out.println("flatMapToPair Result");
JavaPairRDD flatMapToPairResult = linesRDD.flatMapToPair(
new PairFlatMapFunction() {
@Override
public Iterator> call(String s) throws Exception {
List> resultTuple = new ArrayList<>();
String[] tmpList = s.split(" ");
for (String tmpString : tmpList) {
resultTuple.add(new Tuple2<>(tmpString, 1));
}
return resultTuple.iterator();
}
});
flatMapToPairResult.foreach(new VoidFunction>() {
@Override
public void call(Tuple2 stringIntegerTuple2) throws Exception {
System.out.println(stringIntegerTuple2);
}
});
System.out.println("\n\n");
sparkContext.close();
}
}
========
运行结果:
map Result
You
are
a
bad
man
Just
a
test
job
mapPartitions Result
Just
a
test
job
You
are
a
bad
man
flatMap Result
Just
a
test
job
You
are
a
bad
man
flatMapToPair Result
(Just,1)
(a,1)
(test,1)
(job,1)
(You,1)
(are,1)
(a,1)
(bad,1)
(man,1)