引入java pom依赖
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.3.1</version>
</dependency>
1.获取JavaSparkContext上下文对象,用于读取数据得到RDD,并设置
SparkConf conf = new SparkConf().setAppName(args[0]).setMaster("local[2]");//线程数2集群修改为"spark://mini1:7077"
JavaSparkContext sc = new JavaSparkContext(conf);
sc.setCheckpointDir("hdfs://mini1:9000/checkPoint");//设置分布式缓存数据
2.加载数据得到RDD
JavaRDD<String> data = sc.textFile("hdfs://mini1:9000/3.txt");//读取hdfs文件
//JavaRDD<String> data = sc.textFile("C:\3.txt");//读取本地文件
//JavaRDD<Object> data = sc.parallelize(new ArrayList<>());//读取内存,将list转化为rdd 这个rdd为空,需要提前存入数据在转化
4.数据清洗处理
//按空格切割每一条数据返回一个新的rdd new FlatMapFunction<加载后的格式,处理后的格式>()
JavaRDD<String> wordsJavaDDR = data.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String line) {
List<String> strings = Arrays.asList(line.split(" "));
return strings.iterator();
}
});
//将rdd转化成二元的rdd,拼接参数new PairFunction<加载后的key,处理后的key,拼接的value>()
JavaPairRDD<String, Integer> wordAndOne = wordsJavaDDR.mapToPair(new PairFunction<String, String, Integer>() {
@Override
public Tuple2<String, Integer> call(String word) throws Exception {//拼接的value
return new Tuple2<>(word, 1);
}
});
//聚合相同key的rdd并统计次数
JavaPairRDD<String,Integer> result = wordAndOne.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
});
//分布式缓存数据
result.checkpoint();
5.降序
//key-value反序value-key
JavaPairRDD<Integer, String> ReverseOrder = result.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
@Override
public Tuple2<Integer, String> call(Tuple2<String, Integer> ReverseOrder) throws Exception {
return new Tuple2<>(ReverseOrder._2, ReverseOrder._1);
}
});
//降序
JavaPairRDD<Integer, String> Desc = ReverseOrder.sortByKey(false);
//本地缓存数据
Desc.check();//内存缓存
//Desc.persist(org.apache.spark.api.java.StorageLevels.MEMORY_ONLY);设置级别缓存 //Desc.unpersist();清除缓存
//反序得到res
6.加载数据得到RDD
List<Tuple2<String, Object>> collect = res.collect();//shuffle计算
for (Tuple2<String, Object> tuple2 : collect) { //遍历最终结果
System.out.println(tuple2._1+":"+tuple2._2);
}
7.局部聚合与分区聚合combiner机制
JavaPairRDD<Integer, Integer> rdd = sc.parallelizePairs(list);得到一个RDD
JavaPairRDD<Integer, Integer> result = rdd.aggregateByKey(0, (a, b) -> {//a表示上次一次的v,如果没有表示的初始值,b表示当前的k-v中的v
return a + b;//内部聚合
}, (a, b) -> {
return a + b;//分区聚合
});
//Function2<前一个值的类型, 当前值的类型, 结果返回值的类型,三个值的类型一致>
map.aggregateByKey(0, (Function2<Integer, Integer, Integer>) (integer, integer2) -> null)
8.api功能
rdd<key,value>.mapValues(func) 对rdd<k,v>中的value做替换处理
RDD.persist(StorageLevel.MEMORY_AND_DISK()) 缓存,修改形参可以设置缓存级别,缓存本地与缓存磁盘
RDD1.join(RDD2) RDD<K,V>将两个rdd的key做连接,获取本身数据与对方和自己都有的数据,与mysql的join一样
去重 javaRDD.distinct()
转化为二元的RDD rdd.mapToPair()
先分区内部聚合,再分区聚合
Aggregate聚合所有值,AggregateByKey和Aggregate差不多,也是聚合,不过它是根据Key的值来聚合
多个rdd聚合方法 cogroup
JavaPairRDD<String, Tuple3<Iterable<Integer>, Iterable<Integer>, Iterable<Integer>>> cogroup = javaPairRDD1.cogroup(javaPairRDD2, javaPairRDD3);
参与聚合的所有rdd中,相同的key会聚合再一起,它的value是多元组 TupleN ,Tuple中的每一个元组都是一个迭代器,一个rdd中相同key的value会聚合成一个迭代器,多个rdd会得到多个迭代器,TupleN 是由多个迭代器组成
例如数据格式如下
(e,([],[2],[]))
(d,([1, 1],[],[1, 1]))
(a,([1],[1],[1]))
(b,([2],[1, 4, 1],[2]))
(c,([1],[],[1]))
(f,([],[1],[]))
"()"表示元组"[]"表示迭代器 如果没有这个key,会得到一个空的迭代器
spark在执行的时候会报环境变量异常 需要配置文件winutils.exe
System.setProperty("hadoop.home.dir", "B:\\winutilsmaster\\winutils-master\\hadoop-2.7.1");
spark 2.4在IDEA调试启动的时候会报字符串越界异常
异常信息 java.lang.StringIndexOutOfBoundsException: String index out of range: 20
解决方式,添加pom依赖
<dependency>
<groupId>com.thoughtworks.paranamer</groupId>
<artifactId>paranamer</artifactId>
<version>2.8</version>
</dependency>