Spark小课堂Week3 FirstSparkApp

问题:Java有哪些数据结构

大致有如下几种,其中List与Map是最重要的:

  • List
  • Map
  • Set
  • Array
  • Heap
  • Stack
  • Queue
  • Tree

练习:构造一个1-5的List,把他们打印出来

写法1

        List<Integer> input = Arrays.asList(1, 2, 3, 4, 5);
for (int i = 0; i < input.size(); i++) {
System.out.println(input.get(i));
}

这个写法存在的问题:

  1. 存在额外定义的变量i,需要对i进行逻辑控制(比如不能超过size)。
  2. 无法在循环内部如果对List进行安全更新,会产生逻辑问题。
  3. 这个写法非常的不推荐使用!!!

写法2

        Iterator<Integer> it = input.iterator();
while (it.hasNext()) {
System.out.println("a" + it.next());
}

几点说明:

  1. iterator相当于oracle中游标,拥有数据只读和只能一次性读的特点。
  2. hasNext()和next)()是游标必备的方法,其中hasNext是判断是否有下一条,等同%Found,next是获取下一条数,等同fetch。

    这个写法存在的问题:
  3. 存在额外的对象it,读取方法比较简单,但是也需要记忆。

写法3

        for (Integer i : input) {
System.out.println(i);
}

这是对写法2的优化,逻辑完全等价,是一个语法糖。

写法2和写法3共同存在的问题:

  1. 执行是串行的,对大数量的情况不适合。

写法4

input.parallelStream().forEach(
new Consumer<Integer>() {
@Override
public void accept(Integer a) {
System.out.println(a);
}
}
);

在这个写法中,执行是并行执行的,

从语句特点看是将一个对象出入了forEach方法中,进行一下说明:

  1. 多线程程序,其实是几个互相独立运行的程序,产生了一个问题,我们需要将逻辑传递给给各自独立运行的程序
  2. 由于在Java中对象是全局存储的,所以是唯一可以在独立运行程序中传递的介质。
  3. 但是我们要的传递的是逻辑,比如要转变为对象才能传递,如果变成对象,要做两件事情:
    • 把逻辑,用方法来封装(示例中的apply方法)
    • 把方法,用class或者intereface来封装,更推荐intereface(示例中的Consumer)
      • 因为class既可以包含数据、又可以包含方法,而intereface中只包含方法,在我们的场景中,只需要传递方法
  4. 最后,接口提供方预先将intereface和method定义好,调用者按照模板使用即可。

    存在的问题:
  5. 语句比较长,逻辑也比较复杂

写法5

        input.parallelStream().forEach(
a -> System.out.println(a)
);

这个写法和写法4逻辑没有任何区别,主要是用lambda表达式简化了对象的写法,是一个语法糖。

写法4和写法5共同的问题是:

当数据量进一步扩大,一台机器就算是多线程运行也无法完成的情况下,是无法处理的。

小结

在上述的几个写法中,主要是通过对于List的一系列增强,从而解决了一系列的问题。

  1. 写法2、3相比写法1,使用Iterator增强List,实现了数据的可更新。
  2. 写法4、5相比前面的写法,使用Stream增强Iterator,实现了数据的并发运算。

    但是,还是留下了在更大数据集情况下的处理。这个是时候,我们需要引入Spark。

    Spark中核心是RDD,是对Stream的进一步增强,在并发的基础上,增加了同时在多台机器上的分布式计算。解决了大数据集的问题。

练习:RDD编程

题目

进行RDD操作的训练:

  1. 读取交易记录
  2. 按照SecurityId进行计数
  3. 根据计数,从高到低排序
  4. 输出结果

练习过程:

Step1:获取RDD数据,这个是调用公共方法,请注意的是,PracticePojo是预先准备好的测试数据名称。

JavaRDD<PracticePojo> inputTradeRecords = this.getInputRDD(PracticePojo.class);

Step2:将数据转为Key-Value格式

因为在Spark处理中,reduce、sort、group等操作涉及到在分布式机器间的数据交互,数据必须要有Key来作为分布操作的依据,所以我们首先要将数据格式进行转换。

        JavaPairRDD<String, Integer> mappedTradeRecords = inputTradeRecords.mapToPair(
new PairFunction<PracticePojo, String, Integer>() {
@Override
public Tuple2<String, Integer> call(PracticePojo practicePojo) throws Exception {
return new Tuple2<String, Integer>(practicePojo.getSecurityId(), 1);
}
});

Step3:执行计数操作。

这里会用到reduceByKey方法,这里要注意的是,reduce是一个非常常用的操作,它有两个操作步骤:

  1. 对数据按照Key进行分组
  2. 对每组数据执行算子计算,需要注意reduce的计算必须满足交换律和结合律
    • 这个算子是指,当整个计算过程都满足交换律和结合律后,我们可以用任意两个数据之间的计算关系来定义整个计算关系
    • 比如:sum和count,可以用加法表示,max可以用a>b?a:b这样的计算来表示,min是反过来
        JavaPairRDD<String, Integer> reducedTradeRecords = mappedTradeRecords.reduceByKey(
new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1 + v2;
}
});

Step4:执行排序

这里有两步操作:

  1. 首先是使用mapToPair方法进行数据变形,因为sortByKey方法仅是针对key来排序,而我们原始数据的key并不是我们要的排序字段,所以首先需要将key和value换一下
  2. 用sortByKey执行排序操作,需要注意的是,参数是一个布尔值,默认为升序,false表示降序
     JavaPairRDD<Integer, String> reversedTradeRecords = reducedTradeRecords.mapToPair(
new PairFunction<Tuple2<String, Integer>, Integer, String>() {
@Override
public Tuple2<Integer, String> call(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {
return new Tuple2<Integer, String>(stringIntegerTuple2._2, stringIntegerTuple2._1);
}
}); JavaPairRDD<Integer, String> sortedTradeRecords = reversedTradeRecords.sortByKey(false);

Step5:输出结果

一般我们都是输出一个JavaRDD,这里采用了预先定义的PracticeResultPojo结构,会将排序完的结果映射到这个结构上。

JavaRDD<PracticeResultPojo> resultTradeRecords = sortedTradeRecords.map(
new Function<Tuple2<Integer, String>, PracticeResultPojo>() {
@Override
public PracticeResultPojo call(Tuple2<Integer, String> v1) throws Exception {
PracticeResultPojo resultPojo = new PracticeResultPojo();
resultPojo.setSecurityId(v1._2);
resultPojo.setCount(v1._1);
return resultPojo;
}
});

小结

RDD编程,难点如下:

  1. 采用对象方式来封装逻辑,和stream中处理方式一致,但是由于算子较多,每个算子要求不同,需要有一定练习来熟悉
  2. 输入输出为JavaRDD,但reduce、group、sort等操作需要中间使用mapToPair将JavaRDD转成JavaPairRDD才能操作,会涉及到多次转换
  3. reduce操作中,算子是更高层次的抽象,有一定的理解难度

关于

小课堂是在公司进行内部交流的一系列主题,偏基础,但是比较零散,持续更新中。

Spark小课堂Week3 FirstSparkApp(RDD开发)的更多相关文章

  1. Spark小课堂Week3 FirstSparkApp(Dataframe开发)

    Spark小课堂Week3 FirstSparkApp(代码优化) RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lamb ...

  2. Spark小课堂Week5 Scala初探

    Spark小课堂Week5 Scala初探 Scala是java威力加强版. 对Java的改进 这里会结合StreamingContext.scala这个代码说明下对Java的改进方面. 方便测试方式 ...

  3. Spark小课堂Week6 启动日志详解

    Spark小课堂Week6 启动日志详解 作为分布式系统,Spark程序是非常难以使用传统方法来进行调试的,所以我们主要的武器是日志,今天会对启动日志进行一下详解. 日志详解 今天主要遍历下Strea ...

  4. Spark小课堂Week2 Hello Streaming

    Spark小课堂Week2 Hello Streaming 我们是怎么进行数据处理的? 批量方式处理 目前最常采用的是批量方式处理,指非工作时间运行,定时或者事件触发.这种方式的好处是逻辑简单,不影响 ...

  5. Spark小课堂Week1 Hello Spark

    Spark小课堂Week1 Hello Spark 看到Spark这个词,你的第一印象是什么? 这是一朵"火花",官方的定义是Spark是一个高速的.通用的.分布式计算系统!!! ...

  6. Spark小课堂Week7 从Spark中一个例子看面向对象设计

    Spark小课堂Week7 从Spark中一个例子看面向对象设计 今天我们讨论了个问题,来设计一个Spark中的常用功能. 功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load() ...

  7. Spark小课堂Week4 从控制台看Spark逻辑结构

    Spark小课堂Week4 从控制台看Spark逻辑结构 层级关系: 从监控控制台,我们可以看到如下关系: 一个 Job 包含 n Stage 一个 Stage 包含 n Task Job0解决什么问 ...

  8. Spark踩坑记——从RDD看集群调度

    [TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...

  9. Hive数据分析——Spark是一种基于rdd(弹性数据集)的内存分布式并行处理框架,比于Hadoop将大量的中间结果写入HDFS,Spark避免了中间结果的持久化

    转自:http://blog.csdn.net/wh_springer/article/details/51842496 近十年来,随着Hadoop生态系统的不断完善,Hadoop早已成为大数据事实上 ...

随机推荐

  1. aptana中删除空行

    问题:有一个css文件,写一行样式后,会换行,空一行,再写另一个样式.现在需要把空的一行给去掉. 尝试直接复制空行,但是aptana会把所有的换行都去了,变成了一个文件只有一行.尝试用正则,\r\t\ ...

  2. css笔记19:浮动的案例

    案例一: 1. 首先是01.html文件: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...

  3. 使用 collectionView 实现表头,区头,区尾

    UICollectionView 的使用是跟表的使用是一样,瀑布流的布局会比表的效果更好,这里说一下 collectionView 设置表头, 区头,区尾 设置表头可以约束 collectionVie ...

  4. CSS的总结(选择器,伪类等...)

    关于组合选择器可参考:http://www.cnblogs.com/starof/p/4453458.html 主要内容 CSS概述 CSS和HTML结合的四种方式 CSS样式优先级和代码规范 CSS ...

  5. [改善Java代码]养成良好习惯,显式声明UID

    建议11: 养成良好习惯,显式声明UID 我们编写一个实现了Serializable接口(序列化标志接口)的类, Eclipse马上就会给一个黄色警告:需要增加一个Serial Version ID. ...

  6. Guava: 事件总线EventBus

    EventBus 直译过来就是事件总线,它使用发布订阅模式支持组件之间的通信,不需要显式地注册回调,比观察者模式更灵活,可用于替换Java中传统的事件监听模式,EventBus的作用就是解耦,它不是通 ...

  7. js限制文本框输入字数

    //js代码 <script type="text/javascript"> function checkLen(term){ document.all.termLen ...

  8. ios app名字的多语言支持

    经测试,不同版本的xcode会有操作细节不同,本次环境xcode6.4 1)编辑Info.plist,添加一个新的属性Application has localized display name, 设 ...

  9. android用异步操作AsyncTask编写文件查看器

    Activity程序 package com.example.fileasynctaskproject; import java.io.File; import java.util.ArrayList ...

  10. Agile.Net 组件式开发平台 - 权限管理组件

    RBAC原则       (1)最小权限原则之所以被RBAC所支持,是因为RBAC可以将其角色配置成其完成任务所需要的最小的权限集.       (2)责任分离原则可以通过调用相互独立互斥的角色来共同 ...