SPARK学习

一、SPARK常见RDD操作方法

操作类型函数名作用
转化操作map()参数是函数,函数应用于RDD每一个元素,返回值是新的RDD
flatMap()参数是函数,函数应用于RDD每一个元素,将元素数据进行拆分,变成迭代器,返回值是新的RDD
filter()参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD
distinct()没有参数,将RDD里的元素进行去重操作
union(RDD)参数是RDD,生成包含两个RDD所有元素的新RDD
intersection(RDD)参数是RDD,求出两个RDD的共同元素
subtract(RDD)参数是RDD,将原RDD里和参数RDD里相同的元素去掉
cartesian()参数是RDD,求两个RDD的笛卡儿积
行动操作collect()返回RDD所有元素
count()RDD里元素个数
countByValue()各元素在RDD中出现次数
take(num)从 RDD 中返回 num 个元素
top(num)从 RDD 中返回最前面的 num个元素
takeOrdered(num)(ordering)从 RDD 中按照提供的顺序返回最前面的 num 个元素
takeSample(withReplacement, num, [seed])从 RDD 中返回任意一些元素
reduce()并行整合所有RDD数据,例如求和操作
fold(0)(func)和reduce功能一样,不过fold带有初始值
aggregate(0)(seqOp,combop)和reduce功能一样,但是返回的RDD数据类型和原RDD不一样
foreach(func)对RDD每个元素都是使用特定函数

二、Java中针对专门类型的函数接口

函数名等价函数用途
DoubleFlatMapFunctionFunction>用于 flatMapToDouble,以生成 DoubleRDD
DoubleFunctionFunction用于 mapToDouble,以生成DoubleRDD
PairFlatMapFunctionFunction>>用于 flatMapToPair,以生成 PairRDD
PairFunctionFunction>用 于 mapToPair, 以 生 成PairRDD

生成一个 JavaDoubleRDD、计算 RDD 中每个元素的平方值的示例,这样就可以调用 DoubleRDD 独有的函数了,比如 mean() 和 variance()。

JavaDoubleRDD result = rdd.mapToDouble(
    new DoubleFunction<Integer>() {
        public double call(Integer x) {
            return (double) x * x;
        }
    });
System.out.println(result.mean());

三、Spark 对数据持久化

有时我们希望能多次使用同一个 RDD。如果简单地对 RDD 调用行动操作, Spark 每次都会重算 RDD 以及它的所有依赖。这在迭代算法中消耗格外大,因为迭代算法常常会多次使用同一组数据。
为了避免多次计算同一个 RDD,可以让 Spark 对数据进行持久化。对这个 RDD 调用行动操作前就调用了 persist() 方法。出于不同的目的,我们可以为 RDD 选择不同的持久化级别

级别使用的空间CPU时间是否在内存中是否在磁盘上备注
MEMORY_ONLY
MEMORY_ONLY_SER
MEMORY_AND_DISK中等部分部分如果数据在内存中放不下,则溢写到磁盘上
MEMORY_AND_DISK_SER部分部分如果数据在内存中放不下,则溢写到磁盘上。在内存中存放序列化后的数据
DISK_ONLY

RDD 还有一个方法叫作 unpersist(),调用该方法可以手动把持久化的 RDD 从缓存中移除

四、键值对 RDD

键值对 RDD 是 Spark 中许多操作所需要的常见数据类型。
在Java中,键值对使用的是Scala标准库里面的scala.Tuple2类,可以通过调用new Tuple2(a, b)创建,然后通过tuple._1()和tuple._2()方法访问它的属性。键值对RDD使用的是JavaPairRDD类,可以使用特定的map操作将JavaRDDs转换为JavaPairRDDs,例如mapToPair和flatMapToPair。JavaPairRDD拥有标准RDD和特殊键值对的方法,例如,在下面的代码中使用了reduceByKey对键值对操作,计算每行的文本出现的次数:

JavaRDD<String> lines = sc.textFile("data.txt");
JavaPairRDD<String, Integer> pairs = lines.mapToPair(s -> new Tuple2(s, 1));
JavaPairRDD<String, Integer> counts = pairs.reduceByKey((a, b) -> a + b);
函数名作用
reduceByKey(func)合并具有相同键的值
groupByKey()对具有相同键的值进行分组
combineByKey( createCombiner,mergeValue,mergeCombiners,partitioner)使用不同的返回类型合并具有相同键的值
mapValues(func)对 pair RDD 中的每个值应用一个函数而不改变键
flatMapValues(func)一个返回迭代器的函数, 然后对返回的每个元素都生成一个对应原键的键值对记录。 通常用于符号化
keys()返回一个仅包含键的 RDD
values()返回一个仅包含值的 RDD
sortByKey()返回一个根据键排序的 RDD
subtractByKey删掉 RDD 中键与 other RDD 中的键相同的元素
join(RDD)对两个 RDD 进行内连接
rightOuterJoin(RDD)对两个 RDD 进行连接操作,确保第一个 RDD 的键必须存在(右外连接)
leftOuterJoin(RDD)对两个 RDD 进行连接操作,确保第二个 RDD 的键必须存在(左外连接)
cogroup(RDD)将两个 RDD 中拥有相同键的数据分组到一起

Java 没有自带的二元组类型,因此 Spark 的 Java API 让用户使用 scala.Tuple2 类来创建二元组。这个类很简单: Java 用户可以通过 new Tuple2(elem1, elem2) 来创建一个新的二元组,并且可以通过 ._1() 和 ._2() 方法访问其中的元素。

        JavaRDD<String> input = sc.textFile("D:\\spark-2.3.1-bin-hadoop2.7\\README.md");
        // 筛选掉长度超过20 个字符的行
        Function<scala.Tuple2<String, String>, Boolean> longWordFilter =
                new Function<scala.Tuple2<String, String>, Boolean>() {
                    public Boolean call(scala.Tuple2<String, String> keyValue) {
                        return (keyValue._2().length() < 20);
                    }
                };

        JavaPairRDD<String, String> resultPair = input.mapToPair(new PairFunction<String, String, String>() {
            @Override
            public scala.Tuple2<String, String> call(String s) throws Exception {
                return new scala.Tuple2(s, 1);
            }
        }).filter(longWordFilter);

五、Spark支持的一些常见格式

格式名称结构化备注
文本文件普通的文本文件,每行一条记录
JSON半结构化常见的基于文本的格式,半结构化;大多数库都要求每
CSV非常常见的基于文本的格式,通常在电子表格应用中使用
SequenceFiles一种用于键值对数据的常见 Hadoop 文件格式
Protocol buffers一种快速、节约空间的跨语言格式
对象文件用来将 Spark 作业中的数据存储下来以让共享的代码读取。改变类的时候它会失效,因为它依赖于 Java 序列化
①读取一个文本文件
JavaRDD<String> input = sc.textFile("file:///home/holden/repos/spark/README.md")
JavaPairRDD<String, String> inputRDD = sc.wholeTextFiles("file:///home/holden/repos/spark/README.md");
①保存文本文件
result.saveAsTextFile(outputFile)
②读取JSON
class ParseJson implements FlatMapFunction<Iterator<String>, Person> {
    public Iterable<Person> call(Iterator<String> lines) throws Exception {
        ArrayList<Person> people = new ArrayList<Person>();
        ObjectMapper mapper = new ObjectMapper();
        while (lines.hasNext()) {
            String line = lines.next();
            try {
            people.add(mapper.readValue(line, Person.class));
            } catch (Exception e) {
            // 跳过失败的数据
            }
        }
        return people;
    }
}
JavaRDD<String> input = sc.textFile("file.json");
JavaRDD<Person> result = input.mapPartitions(new ParseJson());
②保存JSON
class WriteJson implements FlatMapFunction<Iterator<Person>, String> {
    public Iterable<String> call(Iterator<Person> people) throws Exception {
        ArrayList<String> text = new ArrayList<String>();
        ObjectMapper mapper = new ObjectMapper();
        while (people.hasNext()) {
            Person person = people.next();
            text.add(mapper.writeValueAsString(person));
        }
        return text;
    }
}
JavaRDD<Person> result = input.mapPartitions(new ParseJson()).filter(
new LikesPandas());
JavaRDD<String> formatted = result.mapPartitions(new WriteJson());
formatted.saveAsTextFile(outfile);
③读取CSV

使用 textFile() 读取 CSV

public static class ParseLine implements Function<String, String[]> {
    public String[] call(String line) throws Exception {
        CSVReader reader = new CSVReader(new StringReader(line));
        return reader.readNext();
    }
}
JavaRDD<String> csvFile1 = sc.textFile(inputFile);
JavaPairRDD<String[]> csvData = csvFile1.map(new ParseLine());
③完整读取 CSV
public static class ParseLine
    implements FlatMapFunction<Tuple2<String, String>, String[]> {
    public Iterable<String[]> call(Tuple2<String, String> file) throws Exception {
        CSVReader reader = new CSVReader(new StringReader(file._2()));
        return reader.readAll();
    }
}
JavaPairRDD<String, String> csvData = sc.wholeTextFiles(inputFile);
JavaRDD<String[]> keyedRDD = csvData.flatMap(new ParseLine());
④读取 SequenceFile
public static class ConvertToNativeTypes implements
    PairFunction<Tuple2<Text, IntWritable>, String, Integer> {
    public Tuple2<String, Integer> call(Tuple2<Text, IntWritable> record) {
        return new Tuple2(record._1.toString(), record._2.get());
    }
}
JavaPairRDD<Text, IntWritable> input = sc.sequenceFile(fileName, Text.class,
    IntWritable.class);
JavaPairRDD<String, Integer> result = input.mapToPair(
    new ConvertToNativeTypes());
⑤操作对象文件
sc.objectFile()
saveAsObjectFile

六、SpringBoot+Spark

1、POM
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>2.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>14.0.1</version>
        </dependency>
2、demo代码
package cn.pzh.spark.demo.A01SparkDemo;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
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.Function2;
import org.apache.spark.api.java.function.PairFunction;

public class WordsCountDemo {

    public static void main(String[] args) {

        // 1、创建一个Java版本的Spark Context
        // setAppName:设置应用名字,此名字会在Spark web UI显示
        // setMaster:设置主节点URL,本例使用“local”是指本机单线程
        //            local[K]:本机K线程
        //            local[*]:本机多线程,线程数与服务器核数相同
        //            spark://HOST:PORT:Spark集群地址和端口,默认端口为7077
        //            mesos://HOST:PORT:Mesos集群地址和端口,默认端口为5050
        //            yarn:YARN集群
        SparkConf conf = new SparkConf().setAppName("WordCount").setMaster("local");
        // 创建JavaSparkContext对象
        JavaSparkContext sc = new JavaSparkContext(conf);

        // 2、读取数据
        // ①并行集合Parallelized Collections
        List<Integer> data = Arrays.asList(1, 2, 3, 4, 5);
        // 创建 RDD 最简单的方式就是把程序中一个已有的集合传给 SparkContext 的 parallelize()方法
        JavaRDD<Integer> distData = sc.parallelize(data);
        // 调用reduce方法计算集合里面所有元素的总和
        int count= distData.reduce((a, b) -> a + b);
        System.out.println("总和为:" + count);

        // ②外部存储中读取数据来创建 RDD。读取我们的输入数据
        JavaRDD<String> input = sc.textFile("D:\\spark-2.3.1-bin-hadoop2.7\\README.md");

        // 3、操作数据
        // ①转化操作filter、union、map、flatMap:RDD 的转化操作是返回新 RDD 的操作。
        // filter()接收一个函数,并将 RDD 中满足该函数的元素放入新的 RDD 中返回
        JavaRDD<String> inputRDD = input.filter(x -> x.contains("Spark"));
        // map()接收一个函数,把这个函数用于 RDD 中的每个元素,将函数的返回结果作为结果存入RDD中对应元素的值
        // 计算 RDD 中各值的平方
        JavaRDD<Integer> result = distData.map(new Function<Integer, Integer>() {
            public Integer call(Integer x) {
                return x * x;
            }
        });
        System.out.println(StringUtils.join(result.collect(), ","));
        // flatMap切分为单词
        JavaRDD<String> words = input.flatMap(new FlatMapFunction<String, String>() {
            public Iterator<String> call(String x) {
                return Arrays.asList(x.split(" ")).iterator();
            }
        });

        // ②行动操作:会把最终求得的结果返回到驱动器程序, 或者写入外部存储系统中
        System.out.println("Spark在inputRDD有 " + inputRDD.count() + " 行");
        for (String line : inputRDD.take(10)) {
            System.out.println(line);
        }

        // 转换为键值对并计数
        JavaPairRDD<String, Integer> counts = words.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public scala.Tuple2<String, Integer> call(String s) throws Exception {
                return new scala.Tuple2(s, 1);
            }
        }).reduceByKey(new Function2<Integer, Integer, Integer>() {
            public Integer call(Integer x, Integer y) {
                return x + y;
            }
        });
        // 筛选掉长度超过20 个字符的行
        Function<scala.Tuple2<String, String>, Boolean> longWordFilter =
                new Function<scala.Tuple2<String, String>, Boolean>() {
                    public Boolean call(scala.Tuple2<String, String> keyValue) {
                        return (keyValue._2().length() < 20);
                    }
                };
        JavaPairRDD<String, String> resultPair = input.mapToPair(new PairFunction<String, String, String>() {
            @Override
            public scala.Tuple2<String, String> call(String s) throws Exception {
                return new scala.Tuple2(s, 1);
            }
        }).filter(longWordFilter);

        // 将统计出来的单词总数存入一个文本文件,引发求值
        counts.saveAsTextFile("D:\\spark-2.3.1-bin-hadoop2.7\\README1.md");
        sc.close();

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值