spark支持两种RDD操作:transformation和action
transformation操作会针对已有的RDD创建一个新的RDD,而action主要对RDD进行最后的操作,比如遍历,reduce,保存文件等,并可以返回结果给drive程序
例如map就是一个transformation操作,他作用域已有RDD的每个元素传入一个自定义的函数,并获取一个新的元素,然后所有的新元素组成一个引得RDD.而reduce就是一种action操作,它用于对RDD中的所有元素进行聚合操作,并获取一个最终的结果,返回给drive程序
transformation特点就是lazy特性,lazy特性是指如果一个spark应用总之定义了transformation操作那么及时你执行该应用,这些操作也不会执行.也就是说transformation是不会触发spark程序的执行的,他们只是记录了对RDD所做的操作,但是不会自发的执行,只有当transformation只后接着执行一个action操作那么所有的transformation才会执行.
spark通过lazy特性来进行底层的spark应用执行的优化,避免产生过多的中间结果
action操作执行会触发一个spark job的运行,从而触发这个action之前所有的transformation执行,这是action的特性.
常用的transformation介绍
- map 将RDD中的每个元素传入自定义函数,获取一个新元素,然后用新元素组成一个新的RDD
- filter 对RDD中每个元素进行判断,如果返回是true则保留,返回false则剔除
- flatMap 与map类似,但是对每个元素都可以返回一个或多个新的元素(将文本拆分成多个单词)
- groupByKey 根据key进行分组,每个可以对应一个iterable
- reduceByKey 对每个key对应value进行reduce操作
- sortByKey 根据key进行排序
- join: 对两个包含<key,value>对的RDD进行join操作,每个key join上的pair都会传入自定义函数进行处理
- cogroup 同join但是是每个key对应的iterable都会传入自定义函数进行处理
常用action介绍
reduce 将RDD中的所有元素进行聚合操作,第一个和第二个元素聚合,值与第三个元素聚合,值与第四个元素聚合,以此类推
collect 将RDD中的所有元素获取本地客户端
count 获取RDD元素总数
take(n) 获取RDD中的前n个元素
saveAsTextFile 将RDD元素保存到文件中,对每个元素调用tostring方法
countByKey 对每个key对应的值进行count计数
foreach 遍历RDD中的每个元素
transformation案例
map
是对任何算数据类型的RDD都可以调用的
在java中,map算子接收的参数是Function对象
创建的Function对象,一定会让你设置第二个参数,这个泛型参数,就是返回新元素的类型
同时call()方法的返回类型,也必须与第二个个泛型类型同步
在call()可以对原始数据进行各种操作,并返回一组新的元素组成一个新的RDD
import org.apache.spark.SparkConf;
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.VoidFunction;
import java.util.Arrays;
import java.util.List;
public class Traqnstfromation {
public static void main(String[] args) {
myMap(); //调用
}
//map算子
private static void myMap(){
SparkConf conf = new SparkConf()
.setMaster("local")
.setAppName("myMap");
JavaSparkContext sc = new JavaSparkContext(conf);
//构建一个集合
List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);
//并行化集合,初始化RDD
JavaRDD<Integer> numberRDD = sc.parallelize(number);
//使用map算子,将集合中每个元素*2
JavaRDD<Integer> map = numberRDD.map(new Function<Integer, Integer>() {
@Override
public Integer call(Integer integer) throws Exception {
return integer * 2;
}
});
//打印结果
map.foreach(new VoidFunction<Integer>() {
@Override
public void call(Integer integer) throws Exception {
System.out.println(integer);
}
});
}
}
结果
filter
传入的也是faction,其他的输赢注意点,实际和map是一样的
每一个RDD初始化中的元素,都会传入call()方法,此时你可以执行各种自定义的计算逻辑
如果你想要在新的RDD中保留这个元素,那么就返回true;否则,不想保留这个元素,返回false
import org.apache.spark.SparkConf;
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.VoidFunction;
import java.util.Arrays;
import java.util.List;
public class Transformation_filter {
public static void main(String[] args) {
myFilter();
}
private static void myFilter(){
SparkConf conf = new SparkConf()
.setAppName("myFilter")
.setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
//模拟集合
List<Integer> number = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//并行化集合,初始化RDD
JavaRDD<Integer> numberRDD = sc.parallelize(number);
//对初始化RDD执行filter算子,将其中的偶数过滤出来
JavaRDD<Integer> filter = numberRDD.filter(new Function<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) throws Exception {
return integer % 2 == 0;
}
});
//输出结果
filter.foreach(new VoidFunction<Integer>() {
@Override
public void call(Integer integer) throws Exception {
System.out.println(integer);
}
});
}
}
flatMap
在java中,接受的参数是flatMapFunction
我们需要自己定义FlatMapFunction的第二个泛型类型,即,代表了返回的新元素的类型
call()方法,返回类型,不是Object。而是Iterable,这里的Object也与第二个泛型类型相同
flatMap其实就是,接受原始RDD中的每个元素,并进行各种逻辑计算和处理。返回多个元素
多个元素,即封装在Iterable中,可以使用ArrayList等集合
import org.apache.spark.SparkConf;
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.VoidFunction;
import java.util.Arrays;
import java.util.List;
public class Transformation_flatmap {
public static void main(String[] args) {
myFlatMap();
}
private static void myFlatMap(){
SparkConf conf = new SparkConf()
.setMaster("local")
.setAppName("myFlatMap");
JavaSparkContext sc = new JavaSparkContext(conf);
//模拟集合
List<String> linelist = Arrays.asList("hello jok", "my name is tom");
//初始化RDD
JavaRDD<String> linelistRDD = sc.parallelize(linelist);
//对RDD执行flatmap算子
JavaRDD<String> words = linelistRDD.flatMap(new F