reduce
案例:有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
reduce操作的原理
首先将第一个和第二个元素,传入call()方法,进行计算,会获取一个结果,比如1 + 2 = 3
接着将该结果与下一个元素传入call()方法,进行计算,比如3 + 3 = 6
以此类推
所以reduce操作的本质,就是聚合,将多个元素聚合成一个元素
Java版本
public static void reduce() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("reduceJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
// reduce操作的原理:
// 首先将第一个和第二个元素,传入call()方法,进行计算,会获取一个结果,比如1 + 2 = 3
// 接着将该结果与下一个元素传入call()方法,进行计算,比如3 + 3 = 6
// 以此类推
// 所以reduce操作的本质,就是聚合,将多个元素聚合成一个元素
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
Integer sum = numsRDD.reduce(new Function2() {
@Override
public Integer call(Integer integer, Integer integer2) throws Exception {
return integer + integer2;
}
});
System.out.println("sum = " + sum);
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def reduce(): Unit = {
val conf = new SparkConf().setAppName("reduceScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
val sum = numsRDD.reduce(_ + _)
println("sum = " + sum)
}
collect
不用foreach action操作,在远程集群上遍历rdd中的元素,而使用collect操作,将分布在远程集群上的doubleNumbers RDD的数据拉取到本地
这种方式,一般不建议使用,因为如果rdd中的数据量比较大的话,比如超过1万条
那么性能会比较差,因为要从远程走大量的网络传输,将数据获取到本地
此外,除了性能差,还可能在rdd中数据量特别大的情况下,发生oom异常,内存溢出
因此,通常,还是推荐使用foreach action操作,来对最终的rdd元素进行处理
Java版本
public static void collect() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("collectJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
JavaRDD doubleNumsRDD = numsRDD.map(new Function() {
@Override
public Integer call(Integer integer) throws Exception {
return integer * 2;
}
});
// 不用foreach action操作,在远程集群上遍历rdd中的元素,而使用collect操作,将分布在远程集群上的doubleNumbers RDD的数据拉取到本地
// 这种方式,一般不建议使用,因为如果rdd中的数据量比较大的话,比如超过1万条
// 那么性能会比较差,因为要从远程走大量的网络传输,将数据获取到本地
// 此外,除了性能差,还可能在rdd中数据量特别大的情况下,发生oom异常,内存溢出
// 因此,通常,还是推荐使用foreach action操作,来对最终的rdd元素进行处理
List doubleNums = doubleNumsRDD.collect();
for(Integer integer : doubleNums) {
System.out.println("integer = " + integer);
}
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def collect(): Unit = {
val conf = new SparkConf().setAppName("collectScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
val doubleNumsRDD = numsRDD.map(_ * 2)
val doubleNums = doubleNumsRDD.collect()
for(e <- doubleNums) println("e = " + e)
}
count
count操作,统计它有多少个元素
Java版本
public static void count() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("countJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
// 对rdd使用count操作,统计它有多少个元素
long countNum = numsRDD.count();
System.out.println("countNum = " + countNum);
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def count(): Unit = {
val conf = new SparkConf().setAppName("countScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
val countNumber = numsRDD.count()
println("countNumber = " + countNumber)
}
take
take操作,与collect类似,也是从远程集群上,获取rdd的数据,但是collect是获取rdd的所有数据,take只是获取前n个数据
Java版本
public static void take() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("takeJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
// take操作,与collect类似,也是从远程集群上,获取rdd的数据
// 但是collect是获取rdd的所有数据,take只是获取前n个数据
List takeNumbers = numsRDD.take(5);
for(Integer integer : takeNumbers) {
System.out.println("integer = " + integer);
}
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def take(): Unit = {
val conf = new SparkConf().setAppName("takeScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
val takeNumbers = numsRDD.take(5)
for(e <- takeNumbers) println("e = " + e)
}
saveAsTextFile
直接将rdd中的数据,保存在HFDS文件中
但是要注意,我们这里只能指定文件夹,也就是目录
doubleNumbers.saveAsTextFile("hdfs://spark1:9000/double_number.txt");
那么实际上,会保存为目录中的/double_number.txt/part-00000文件
Java版本
public static void saveAsTextFile() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("saveAsTextFileJava");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
JavaRDD doubleNumsRDD = numsRDD.map(new Function() {
@Override
public Integer call(Integer integer) throws Exception {
return integer * 2;
}
});
doubleNumsRDD.saveAsTextFile("hdfs://hadoop-100:9000/doubleNumber.txt");
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def saveAsTextFile(): Unit = {
val conf = new SparkConf().setAppName("saveAsTextFileScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
numsRDD.saveAsTextFile("hdfs://hadoop-100:9000/numsRDD")
}
countByKey
这就是countByKey的作用,统计每个key对应的元素个数
countByKey返回的类型,直接就是Map
Java版本
public static void countByKey() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("countByKeyJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 创建集合
List> scoreList = Arrays.asList(
new Tuple2("class1", 80),
new Tuple2("class2", 80),
new Tuple2("class1", 95),
new Tuple2("class2", 85)
);
// 并行化集合,创建初始化RDD
JavaPairRDD scoreListRDD = javaSparkContext.parallelizePairs(scoreList);
// 对rdd应用countByKey操作,统计每个班级的学生人数,也就是统计每个key对应的元素个数
// 这就是countByKey的作用,统计每个key对应的元素个数
// countByKey返回的类型,直接就是Map
Map classNumber = scoreListRDD.countByKey();
for (Map.Entry map : classNumber.entrySet()) {
System.out.println(map.getKey() + "班级有" + map.getValue() + "人");
}
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def countByKey(): Unit = {
val conf = new SparkConf().setAppName("countByKeyScala").setMaster("local")
val context = new SparkContext(conf)
val scores = Array(("class1", 80), ("class2", 80), ("class1", 95), ("class2", 85))
val scoreRDD = context.parallelize(scores)
val classNumber = scoreRDD.countByKey()
for(e <- classNumber) println(e._1 + "班级有" + e._2 + "人")
}
foreach
foreach,遍历RDD的元素,在远程集群上执行
Java版本
public static void foreach() {
// 创建SparkConf
SparkConf sparkConf = new SparkConf().setAppName("foreachJava").setMaster("local");
// 创建JavaSparkContext
JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);
// 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
// 创建集合
List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行化集合,创建初始化RDD
JavaRDD numsRDD = javaSparkContext.parallelize(nums);
numsRDD.foreach(new VoidFunction() {
@Override
public void call(Integer integer) throws Exception {
System.out.println("integer = " + integer);
}
});
// 关闭javaSparkContext
javaSparkContext.close();
}
scala版本
def foreach(): Unit = {
val conf = new SparkConf().setAppName("foreachScala").setMaster("local")
val context = new SparkContext(conf)
val numsRDD = context.parallelize(1 to 10)
numsRDD.foreach(num => println("num = " + num))
}