第2课:Scala面向对象彻底精通及Spark源码阅读-杭州-Frank

第2课:Scala面向对象彻底精通及Spark源码阅读-杭州-Frank
第2课:Scala面向对象彻底精通及Spark源码阅读-杭州-Frank

第二课:Scala面向对象彻底精通及Spark源码阅读

杭州-Frank

一、Scala中的类、object实战详解

Scala是纯面向对象语言。谈面向对象,一定要谈类,类把数据和代码封装起来。

跟Java一样,Scala也是用关键字class来定义类。示例如下:

scala>class HiScala{

|private var name="Spark"

|def sayName(){println(name)}

|def getName=name

|}

defined class HiScala

以上代码,定义了一个名称为HiScala的类,默认情况下是public级别,所以public关键字可以不写。

?定义了一个属性name,为可变变量,访问级别为private,在类的外面不能被访问!?定义一个函数:sayName

?定义一个函数:getName

在Scala中,变量与类中的方法是同等级的,可以直接相互赋值。

创建类实例

scala>val scal=new HiScala

scal:HiScala=HiScala@1c655221

//此时,scal就是HiScala类的一个实例。但是,在Scala中我们一边不会用new来创建类的实例,而是用apply工厂方法模式来创建。

//调用scal的sayName方法,用于打印出name成员的值。

scala>scal.sayName()

Spark

//由于sayName没有传参数,所以可以把括号去掉,这样更简洁。

scala>scal.sayName

Spark

//调用getName方法,访问name成员的值

scala>scal.getName

res2:String=Spark

//此时确实返回了name的值。

//该示例中name是私有的,所以不能直接访问scal实例的name,如下访问就出错了。scala>https://www.360docs.net/doc/7e11366008.html,

:10:error:variable name in class HiScala cannot be accessed in HiScala

https://www.360docs.net/doc/7e11366008.html,

^

get与set

Scala的get和set跟Java的get和set有很大的差异。

在Scala中,如果给变量前定义了private,那么Scala解释器会给这个变量自动生成private 的get和set方法;

如果变量前没有定义了private,那么解释器会给这个变量自动生成public的get和set方法,这样就可以直接访问该类的实例对象的成员变量,实际访问的是它的set和get方法。

//我们重新改造上面的类,把属性name前面的private访问级别去掉。

scala>class HiScala{

|var name="Spark"//去掉了private关键字

|def sayName(){println(name)}

|def getName=name

|}

defined class HiScala

scala>val scal=new HiScala

scal:HiScala=HiScala@1e6d1014

//访问name属性,值为Spark

scala>https://www.360docs.net/doc/7e11366008.html,

res4:String=Spark

//此时虽然是访问属性name,但其实不是直接访问var指定的变量name,而是Scala解释器自动给name生成public级别的get和set方法。

//修改name属性

scala>https://www.360docs.net/doc/7e11366008.html,="Scala"

https://www.360docs.net/doc/7e11366008.html,:String=Scala

//再次访问name属性,值已经变为Scala

scala>https://www.360docs.net/doc/7e11366008.html,

res5:String=Scala

自定义的get和set

scala>class Person{

|private var myName="Flink"

|def name=this.myName//自定义get方法

|def name_=(newName:String){//自定义set方法,注意下划线和等号之间没有空格!

|myName=newName

|println("Hi"+myName)

|}

|}

defined class Person

//luck为Person类的实例

scala>val luck=new Person

luck:Person=Person@6a5fc7f7

//通过自定义的get方法,访问到了myName属性

scala>https://www.360docs.net/doc/7e11366008.html,

res0:String=Flink

//调用自定义的set方法,修改了myName属性

scala>https://www.360docs.net/doc/7e11366008.html,="Spark"

Hi Spark

https://www.360docs.net/doc/7e11366008.html,:String=Spark

//再次访问myName属性,发现属性值已经变成Spark

scala>https://www.360docs.net/doc/7e11366008.html,

res2:String=Spark

//修改上面的示例,仅仅暴露属性的get方法,没有为其复写set方法。但是提供一个名为update的方法用来修改该属性的值。

scala>class Person{

|private var myName="Flink"

|def name=this.myName//get方法

|def update(newName:String){

|myName=newName

|println("Hi"+myName)

|}

|}

defined class Person

//luck为Person类的实例

scala>val luck=new Person

luck:Person=Person@7c469c48

//通过自定义的get方法,访问myName属性值,初始值为Flink

scala>https://www.360docs.net/doc/7e11366008.html,

res4:String=Flink

//想直接通过set方法来修改myName,会提示出错,因为没有复写set方法。scala>https://www.360docs.net/doc/7e11366008.html,="Hadoop"

:9:error:value name_=is not a member of Person

https://www.360docs.net/doc/7e11366008.html,="Hadoop"

^

//通过额外提供的update方法来修改属性

scala>luck.update("Hadoop")

Hi Hadoop

//再次查看myName属性值,发现已经变成了Hadoop

scala>https://www.360docs.net/doc/7e11366008.html,

res6:String=Hadoop

private[this]

private[this]至关重要的,在Spark源码中随处可见。

代表属性或方法为对象私有!在类私有的基础上更强一层的控制。

//定义一个类:Person

scala>class Person{

|private var myName="Flink"

|def name=this.myName

|def update(newName:String){

|myName=newName

|println("Hi"+myName)

|}

|def talk(p:Person)={

|println("hello:"+https://www.360docs.net/doc/7e11366008.html,)

|}

|}

defined class Person

//定义p1为Person对象

scala>val p1=new Person

p1:Person=Person@14555e0a

//定义p2为Person对象

scala>val p2=new Person

p2:Person=Person@1b2abca6

//把p1的myName属性值改为p1

scala>p1.update("p1")

Hi p1

//把p2的myName属性值改为p2

scala>p2.update("p2")

Hi p2

//查看p1的myName属性值,此时已经改为p1

scala>https://www.360docs.net/doc/7e11366008.html,

res14:String=p1

//查看p2的myName属性值,此时已经改为p2

scala>https://www.360docs.net/doc/7e11366008.html,

res15:String=p2

//调用p1的talk方法,传入p2对象,打印出p2的myName属性值

scala>p1.talk(p2)

hello:p2

//我们修改一下代码,看看下面代码:

scala>class Person{

|private[this]var name="Flink"

|def update(newName:String){

|name=newName

|println("Hi"+name)

|}

|def talk(p:Person)={

|println("hello:"+https://www.360docs.net/doc/7e11366008.html,)

|}

|}

:15:error:value name is not a member of Person

println("hello:"+https://www.360docs.net/doc/7e11366008.html,)

^

//此时,在定义类时就报错!因为talk方法中p参数是Person类的对象,而name属性被限制为private[this],所以只能在Person类内部使用,Person类的对象无权使用。也就是说在Person类中,update方法中可以使用name,但是talk方法访问对象p的name是不允许的!

//private[this]改成private之后,下面的写法就能正常定义,代码如下:

scala>class Person{

|private var name="Flink"

|def update(newName:String){

|name=newName

|println("Hi"+name)

|}

|def talk(p:Person)={

|println("hello:"+https://www.360docs.net/doc/7e11366008.html,)

|}

|}

defined class Person

scala>

构造器的重载

scala>class Person{

|private[this]var name="Flink"

|private[this]var age=10

|def update(newName:String){

|name=newName

|println("Hi"+name)

|}

|

|

|//重载的构造器,首先调用默认的构造器

|def this(name:String){

|this()

|https://www.360docs.net/doc/7e11366008.html,=name

|}

|

|//重载的构造器,调用上面已经存在的构造器|def this(name:String,age:Int){

|this(name)

|this.age=age

|}

|}

defined class Person

在Spark源码中,构造器重载非常常见,如下图所示:

(图一)

从图一的源代码中可以看出,SparkContext类重写了有很多构造器,在创建SparkContext实例对象时,传递不同的参数来调用相应的构造器。

在Spark中,与类名放在一起的构造器为默认构造器,如下所示:

(图二)

默认构造器可以带参数也可以不带参数,在图二所示的源代码SparkContext类中,默认构造器带有一个参数。初始化类成员的工作,都放在默认构造器中完成。在SparkContext 类中,creationSite、allowMultipleContexts等变量,就是在SparkContext类的默认构造器中完成。

object

定义一个类同名的object对象,里面存放静态的成员或者方法,把该object对象称之为该类的伴生对象。

查看SparkContext源码,如下图三所示:

(图三)

在图三中,SparkContext object为SparkContext类的伴生对象,里面存放一系列静态的成员和静态的方法。而且,当我们第一次调用SparkContext时,SparkContext伴生对象会被执行一次,仅此一次。

下面是一个示例:

(图4)

上图中object Person是class Person的伴生对象,class Person称之为object Person的伴生类。伴生对象适合在里面定义一些工具方法,以及存放一些全局唯一的常量,节省空间。

//第一次调用:Person伴生对象的getSalary方法

//此时,我们发现:Person伴生对象被初始化,打印出字符串Scala。

scala>Person.getSalary

Scala

res34:Double=0.0

//第二次调用:Person伴生对象的getSalary方法

//此时,我们发现:Person伴生对象不再需要初始化,没有打印出字符串Scala。

scala>Person.getSalary

res35:Double=0.0

以上示例中确实验证了:伴生对象会被执行一次,仅此一次。

Scala中,我们在定义类的对象时,一般都不会用new类名,再传入参数的方式来定义。而是直接用类名,或者类名加参数的方式。例如,我们重温下面的示例:

我们构造一个数组,其实是调用Array的伴生对象object Array的apply方法。

scala>val array=Array(1,2,3)

array:Array[Int]=Array(1,2,3)

scala>val array=Array.apply(1,2,3)

array:Array[Int]=Array(1,2,3)

以上两种定义数组的方式效果是一样的。apply方法就是当前类的伴生对象的工厂方法。延伸一下,Java水平比较高才编程人员,在构造Java对象时,一般来说不会直接new一个类,而是通过工厂方法模式来创建。而Scala语言中,天生就支持这次模式,所以在具体类对象构造时,一般都是在伴生类的伴生对象的apply方法中去实现!这样可以控制对象的生成。

二、Scala中的抽象类、接口实战详解

abstract

抽象类使用abstract关键字,以Spark源码RDD类为示例,如下图5所示:

(图5)

子类去继承抽象类,跟Java一样,也是使用extends关键字。如JdbcRDD就继承了RDD抽象类,如下:

class JdbcRDD[T:ClassTag](

sc:SparkContext,

getConnection:()=>Connection,

sql:String,

lowerBound:Long,

upperBound:Long,

numPartitions:Int,

mapRow:(ResultSet)=>T=JdbcRDD.resultSetToObjectArray_)

extends RDD[T](sc,Nil)with Logging{

那么JdbcRDD就可以使用父类RDD所有它可以使用的属性和方法。

当然,子类也可以覆盖父类的属性和方法。注意,这里面有个前提,父类的属性和方法没有加final。

一个抽象类,那么里面肯定是定义了某个方法,但是没有又实现体,只有方法的说明。比如:

(图六)

上图代码块中,compute就是RDD抽象类的一个方法,只有说明,没有实现体。

override

在上面JdbcRDD子类中,因为JdbcRDD继承了RDD抽象类,那么在JdbcRDD中一定要复写compute方法。如下所示:

使用override关键字表示复写父类的该方法。除了覆盖父类的方法,也可以使用override来覆盖父类的val属性。父类在定义属性时没有给具体的值,就是抽象属性,在子类中,子类必须覆盖该属性。

trait

相当于Java的接口。在trait定义的类中可以定义抽象方法,但是又没有具体的实现。子类可以使用extends关键字来继承该父类。

以Spark源码中的RDD类为示例,RDD继承了Serializable和Logging两个父类。一个子类如果继承多个父类,那么继承的第一个父类前使用extends关键字,后面的父类使用with关键字。RDD继承的这两个父类,在定义时都使用trait关键字来定义。Scala语法中,不允许一个子类同时继承多个抽象父类,但是允许同时继承多个trait父类。

abstract class RDD[T:ClassTag](

@transient private var_sc:SparkContext,

@transient private var deps:Seq[Dependency[_]]

)extends Serializable with Logging{

下面是Serializable类的源码:

trait的用途,更多的是作为工具方法的容器。我们把通用的功能,放在trait中。一个子类,如果需要把很多通用的功能都混进来,那么就需要继承多个trait父类,继承的第一个父类使用extends,后面的父类使用with。Spark源码Master类就是一个示例,继承了多个父类。

三、综合案例及Spark源码解析

阅读Spark源码中的SparkContext类,熟悉第一课和本课的知识点。

YY频道在线:(20:00) 68917580;

熊猫TV转播地址:

https://www.360docs.net/doc/7e11366008.html,/340992 20:00IMF传奇课程

6:00源码大师之路

spark+openfire 源代码部署

spark+openfire二次开发(一) 文章分类:Java编程 1.准备工作: 到官网上下载Openfire 3.6.4,并通过svn下载openfire、Spark和SparkWeb 的源代码 官网地址如下: https://www.360docs.net/doc/7e11366008.html,/downloads/index.jsp 注意官网上最新的Spark版本是2.5.8,其jdk环境最好使用1.6的版本。 2.环境搭建——spark源码安装配置 双击openfire_3_6_4.exe进行openfire的安装,安装过程很简单,不介绍了。 本例的开发环境是基于Eclipse的。 1)选择File——New——Project——Java Project。 输入项目工程名spark Contents中选择"Create project from existiing source",然后把spark 文件所在的文件夹加进去..

点击Finish。 2)生成Spark: 点击Window::Show View::Ant 右击Ant面板,选择Add Buildfiles 展开spark::build文件夹,选择build.xml,点击"OK" 在Ant面板,展开Spark,双击"release",等一段时间,会提示"Build Successful"。 3)运行Spark: 点击Run::Open Debug Dialog...,出现"Run"窗口 选择"Java Application",右键点击"New"按钮. 在"Main"标签页,将New_configuration换成Spark. 点击Project::Browse按钮,选择Spark,再点OK.

如何阅读别人代码

如何阅读别人代码 code reading ++++++++++++ 第一章: 导论 ++++++++++++ 1.要养成一个习惯, 经常花时间阅读别人编写的高品质代码. 2.要有选择地阅读代码, 同时, 还要有自己的目标. 您是想学习新的模式|编码风格|还是满足某些需求的方法. 3.要注意并重视代码中特殊的非功能性需求, 这些需求也许会导致特殊的实现风格. 4.在现有的代码上工作时, 请与作者和维护人员进行必要的协调, 以避免重复劳动或产生厌恶情绪. 5.请将从开放源码软件中得到的益处看作是一项贷款, 尽可能地寻找各种方式来回报开放源码社团. 6.多数情况下, 如果您想要了解"别人会如何完成这个功能呢?", 除了阅读代码以外, 没有更好的方法. 7.在寻找bug时, 请从问题的表现形式到问题的根源来分析代码. 不要沿着不相关的路径(误入歧途). 8.我们要充分利用调试器|编译器给出的警告或输出的符号代码|系统调用跟踪器|数据库结构化查询语言的日志机制|包转储工具和Windows的消息侦查程序, 定出的bug的位置. 9.对于那些大型且组织良好的系统, 您只需要最低限度地了解它的全部功能, 就能够对它做出修改. 10.当向系统中增加新功能时, 首先的任务就是找到实现类似特性的代码, 将它作为待实现功能的模板. 11.从特性的功能描述到代码的实现, 可以按照字符串消息, 或使用关键词来搜索代码. 12.在移植代码或修改接口时, 您可以通过编译器直接定位出问题涉及的范围, 从而减少代码阅读的工作量. 13.进行重构时, 您从一个能够正常工作的系统开始做起, 希望确保结束时系统能

Apache_Spark源码走读系列篇二

超人学院—Apache Spark源码走读之Task运行期之函数调用关系分析 欢迎转载,转载请注明出处,超人学院。 概要 本篇主要阐述在TaskRunner中执行的task其业务逻辑是如何被调用到的,另外试图讲清楚运行着的task其输入的数据从哪获取,处理 的结果返回到哪里,如何返回。 准备 1.spark已经安装完毕 2.spark运行在local mode或local-cluster mode local-cluster mode local-cluster模式也称为伪分布式,可以使用如下指令运行 MASTER=local[1,2,1024] bin/spark-shell [1,2,1024]分别表示,executor number, core number和内存大小,其中内存大小不应小于默认的512M Driver Programme的初始化过程分析 初始化过程的涉及的主要源文件 1.SparkContext.scala 整个初始化过程的入口 2.SparkEnv.scala 创建BlockManager, MapOutputTrackerMaster, ConnectionManager, CacheManager 3.DAGScheduler.scala 任务提交的入口,即将Job 划分成各个stage的关键 4.TaskSchedulerImpl.scala 决定每个stage可以运行几个task, 每个task分别在哪个executor上运行 5.SchedulerBackend

1.最简单的单机运行模式的话,看LocalBackend.scala 2.如果是集群模式,看源文件 SparkDeploySchedulerBackend 初始化过程步骤详解 步骤1:根据初始化入参生成SparkConf,再根据SparkConf来创建SparkEnv, SparkEnv中主要包含以下关键性组件 1. BlockManager 2. MapOutputTracker 3. ShuffleFetcher 4. ConnectionManager private[spark] val env = SparkEnv.create( conf, "", conf.get("spark.driver.host"), conf.get("spark.driver.port").toInt, isDriver = true, isLocal = isLocal) SparkEnv.set(env) 步骤2:创建TaskScheduler,根据Spark的运行模式来选择相应的SchedulerBackend,同时启动taskscheduler,这一步至为关键 private[spark] var taskScheduler = SparkContext.createTaskScheduler(this, master, appName) taskScheduler.start() TaskScheduler.start目的是启动相应的SchedulerBackend,并启动定时器进行检测 overridedef start() { backend.start() if (!isLocal && conf.getBoolean("spark.speculation", false)) {

java 基础知识之hadoop源码阅读必备(一)

java 程序员你真的懂java吗? 一起来看下hadoop中的如何去使用java的 大数据是目前IT技术中最火热的话题,也是未来的行业方向,越来越多的人参与到大数据的学习行列中。从最基础的伪分布式环境搭建,再到分布式环境搭建,再进入代码的编写工作。这时候码农和大牛的分界点已经出现了,所谓的码农就是你让我做什么我就做什么,我只负责实现,不管原理,也不想知道原理。大牛就开始不听的问自己why?why?why?于是乎,很自然的去看源码了。然而像hadoop这样的源码N多人参与了修改和完善,看起来非常的吃力。然后不管如何大牛就是大牛,再硬的骨头也要啃。目前做大数据的80%都是从WEB开发转变过来的,什么spring mvc框架、SSH框架非常熟悉,其实不管你做了多少年的WEB开发,你很少接触到hadoop中java代码编写的风格,有些人根本就看不懂什么意思。下面我来介绍下hadoop源码怎么看。 hadoop体现的是分布式框架,因此所有的通信都基于RPC来操作,关于RPC的操作后续再介绍。hadoop源码怎么看系列分多个阶段介绍,下面重点介绍下JA V A基础知识。 一、多线程编程 在hadoop源码中,我们能看到大量的类似这样的代码 return executor.submit(new Callable() { @Override public String call() throws Exception { //方法类 } 下面简单介绍下java的多线程编程 启动一个线程可以使用下列几种方式 1、创建一个Runnable,来调度,返回结果为空。 ExecutorService executor = Executors.newFixedThreadPool(5); executor.submit(new Runnable() { @Override public void run() { System.out.println("runnable1 running."); } }); 这种方式启动一个线程后,在后台运行,不用等到结果,因为也不会返回结果 2、创建一个Callable,来调度,有返回结果 Future future1 = executor.submit(new Callable() { @Override public String call() throws Exception { // TODO Auto-generated method stub //具体执行一些内部操作 return "返回结果了!"; } }); System.out.println("task1: " + future1.get());

基于Spark的机器学习资料43、其它SparkML算法简单介绍

Spark ML算法简单介绍 一、线性回归算法 线性回归(Linear Regression),数理统计中回归分析,用来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,其表达形式为y = w'x+e,e为误差服从均值为0的正态分布,其中只有一个自变量的情况称为简单回归,多个自变量的情况叫多元回归。 这个例子中近简化使用房屋面积一个因子作为自变量,y轴对应其因变量房屋价格。所以我们机器学习的线性回归就变为对于给定有限的数据集,进行一元线性回归,即找到一个一次函数y=y(x) + e,使得y满足当x={2104, 1600, 2400, 1416, 3000, ... }, y={400, 330, 369, 232, 540, ... } 如下图所示: 至于公式的求解,大家可以自己去看一下源码或者方程求解,这里就不讲解了。 二、逻辑回归算法 logistic回归本质上是线性回归,只是在特征到结果的映射中加入了一层函数映射,即先把特征线性求和,然后使用函数g(z)将最为假设函数来预测。g(z)可以将连续值映射到0和1上。 它与线性回归的不同点在于:为了将线性回归输出的很大范围的数,例如从负无穷到正无穷,压缩到0和1之间,这样的输出值表达为“可能性”才能说服广大民众。当然了,把大值压缩到这个范围还有个很好的好处,就是可以消除特别冒尖的变量的影响。

三、贝叶斯分类算法 贝叶斯定理 贝叶斯定理解决的是这样一个问题:已知在事件B发生的条件下,事件A的发生概率P(A|B),怎样得到事件A发生的条件下,事件B的发生概率P(B|A)?贝叶斯定理为我们打通了从P(A|B) 到P(B|A) 的道路。 P(B|A) = P(A|B) ×P(B) / P(A) 举例说明,假设已经有了100个email,其中: 垃圾邮件占比60%,即P(Spam) = 0.6 80%的垃圾邮件包含关键字“buy”,即P(Buy|Spam) = 0.8 20%的垃圾邮件不包含关键字“buy” 正常邮件占比40%,即P(NotSpam) = 0.4 10%的正常邮件包含关键字“buy”,即P(Buy|NotSpam) = 0.1 90%的正常邮件不包含关键字“buy” 现在,第101个email 进来了,它包含关键字“buy”,那么它是垃圾邮件的概率P(Spam|Buy) 是多少? P(Spam|Buy) = P(Buy|Spam) ×P(Spam) / P(Buy) P(Buy) = P(Buy|Spam) ×P(Spam) + P(Buy|NotSpam) ×P(NotSpam) P(Spam|Buy) = (0.8 ×0.6) / (0.8 ×0.6 + 0.1 ×0.4) = 0.48 / 0.52 = 0.923 由此得出,这个email 有92.3%的可能是一个垃圾邮件。 四、SVM支持向量机算法 支持向量机是一个类分类器,它能够将不同类的样本在样本空间中践行分割,其中生成的分隔面叫作分隔超平面。给定一些标记好的训练样本,SVM算法输出一个最优化的分隔超平面。 五、决策树算法 决策树就是通过一系列规则对数据进行分类的一种算法,可以分为分类树和回归树两类,分类树处理离散变量的,回归树是处理连续变量。 样本一般都有很多个特征,有的特征对分类起很大的作用,有的特征对分类作用很小,甚至没有作用。如决定是否对一个人贷款是,这个人的信用记录、收入等就是主要的判断依据,而性别、婚姻状况等等就是次要的判断依据。决策树构建的过程,就是根据特征的决定性程度,先使用决定性程度高的特征分类,再使用决定性程度低的特征分类,这样构建出一棵倒立的树,就是我们需要的决策树模型,可以用来对数据进行分类。 决策树学习的过程可以分为三个步骤:1)特征选择,即从众多特征中选择出一个作为当前节点的分类标准; 2)决策树生成,从上到下构建节点;3)剪枝,为了预防和消除过拟合,需要对决策树剪枝。 六、Kmeans聚类算法 聚类(clustering)与分类(classification)的不同之处在于:分类是一种示例式的有监督学习算法,它要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应,很多时候这个条件是不成立的,尤其是面对海量数据的时候;而聚类是一种观察式的无监督学习算法,在聚类之前可以不知道类别甚至不给定类别数量,由算法通过对样本数据的特征进行观察,然后进行相似度或相异度的分析,从而达到“物以类聚”的目的。 七、LDA主题模型算法 隐含狄利克雷分配(LDA,Latent Dirichlet Allocation)是一种主题模型(Topic Model,即从所收集的文档中推测主题)。甚至可以说LDA模型现在已经成为了主题建模中的一个标准,是实践中最成功的主题模型之一。 那么何谓“主题”呢?,就是诸如一篇文章、一段话、一个句子所表达的中心思想。不过从统计模型的角度来说,我们是用一个特定的词频分布来刻画主题的,并认为一篇文章、一段话、一个句子是从一个概率模型中生成的。也就是说在主题模型中,主题表现为一系列相关的单词,是这些单词的条件概率。形象来说,主题就是一个桶,里面装了出现概率较高的单词,这些单词与这个主题有很强的相关性。 LDA可以用来识别大规模文档集(document collection)或语料库(corpus)中潜藏的主题信息。它采用了词

Java面向对象编程上机-练习题汇总

【练习题】类的成员变量: 猜数字游戏:一个类A有一个成员变量v,有一个初值100。定义一个类,对A 类的成员变量v进行猜。如果大了则提示大了,小了则提示小了。等于则提示猜测成功。 【练习题】类的成员变量: 请定义一个交通工具(Vehicle)的类,其中有: 属性:速度(speed),体积(size)等等 方法:移动(move()),设置速度(setSpeed(int speed)),加速speedUp(),减速speedDown()等等. 最后在测试类Vehicle中的main()中实例化一个交通工具对象,并通过方法给它初始化speed,size的值,并且通过打印出来。另外,调用加速,减速的方法对速度进行改变。 【练习题】类的成员变量与方法、构造方法 在程序中,经常要对时间进行操作,但是并没有时间类型的数据。那么,我们可以自己实现一个时间类,来满足程序中的需要。 定义名为MyTime的类,其中应有三个整型成员:时(hour),分(minute),秒(second),为了保证数据的安全性,这三个成员变量应声明为私有。 为MyTime类定义构造方法,以方便创建对象时初始化成员变量。 再定义diaplay方法,用于将时间信息打印出来。 为MyTime类添加以下方法: addSecond(int sec) addMinute(int min) addHour(int hou) subSecond(int sec) subMinute(int min) subHour(int hou) 分别对时、分、秒进行加减运算。 【练习题】构造方法 编写Java程序,模拟简单的计算器。 定义名为Number的类,其中有两个整型数据成员n1和n2,应声明为私有。编写构造方法,赋予n1和n2初始值,再为该类定义加(addition)、减(subtration)、乘(multiplication)、除(division)等公有成员方法,分别对两个成员变量执行加、减、乘、除的运算。 在main方法中创建Number类的对象,调用各个方法,并显示计算结果。 【练习题】构造方法: 编写Java程序,用于显示人的姓名和年龄。 定义一个人类(Person),该类中应该有两个私有属性,姓名(name)和年龄(age)。定义构造方法,用来初始化数据成员。再定义显示(display)方法,将姓名和年龄打印出来。

Linux 0.1.1文件系统的源码阅读

Linux 0.11文件系统的源码阅读总结 1.minix文件系统 对于linux 0.11内核的文件系统的开发,Linus主要参考了Andrew S.Tanenbaum 所写的《MINIX操作系统设计与实现》,使用的是其中的1.0版本的MINIX文件系统。而高速缓冲区的工作原理参见M.J.Bach的《UNIX操作系统设计》第三章内容。 通过对源代码的分析,我们可以将minix文件系统分为四个部分,如下如1-1。 ●高速缓冲区的管理程序。主要实现了对硬盘等块设备进行数据高速存取的函数。 ●文件系统的底层通用函数。包括文件索引节点的管理、磁盘数据块的分配和释放 以及文件名与i节点的转换算法。 ●有关对文件中的数据进行读写操作的函数。包括字符设备、块设备、管道、常规 文件的读写操作,由read_write.c函数进行总调度。 ●涉及到文件的系统调用接口的实现,这里主要涉及文件的打开、关闭、创建以及 文件目录等系统调用,分布在namei和inode等文件中。 图1-1 文件系统四部分之间关系图

1.1超级块 首先我们了解一下MINIX文件系统的组成,主要包括六部分。对于一个360K软盘,其各部分的分布如下图1-2所示: 图 1-2 建有MINIX文件系统的一个360K软盘中文件系统各部分的布局示意图 注释1:硬盘的一个扇区是512B,而文件系统的数据块正好是两个扇区。 注释2:引导块是计算机自动加电启动时可由ROM BIOS自动读入得执行代码和数据。 注释3:逻辑块一般是数据块的2幂次方倍数。MINIX文件系统的逻辑块和数据块同等大小 对于硬盘块设备,通常会划分几个分区,每个分区所存放的不同的文件系统。硬盘的第一个扇区是主引导扇区,其中存放着硬盘引导程序和分区表信息。分区表中得信息指明了硬盘上每个分区的类型、在硬盘中其实位置参数和结束位置参数以及占用的扇区总数。其结构如下图1-3所示。 图1-3 硬盘设备上的分区和文件系统 对于可以建立不同的多个文件系统的硬盘设备来说,minix文件系统引入超级块进行管理硬盘的文件系统结构信息。其结构如下图1-4所示。其中,s_ninodes表示设备上得i节点总数,s_nzones表示设备上的逻辑块为单位的总逻辑块数。s_imap_blocks 和s_zmap_blocks分别表示i节点位图和逻辑块位图所占用的磁盘块数。 s_firstdatazone表示设备上数据区开始处占用的第一个逻辑块块号。s_log_zone_size 是使用2为底的对数表示的每个逻辑块包含的磁盘块数。对于MINIX1.0文件系统该值为0,因此其逻辑块的大小就等于磁盘块大小。s_magic是文件系统魔幻数,用以指明文件系统的类型。对于MINIX1.0文件系统,它的魔幻数是0x137f。

源代码是什么

源代码是什么 源代码(也称源程序),是指一系列人类可读的计算机语言指令。在现代程序语言中,源代码可以是以书籍或者磁带的形式出现,但最为常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码的最终目的是将人类可读的文本翻译成为计算机可以执行的二进制指令,这种过程叫做编译,通过编译器完成。 代码组合 源代码作为软件的特殊部分,可能被包含在一个或多个文件中。一个程序不必用同一种格式的源代码书写。例如,一个程序如果有C语言库的支持,那么就可以用C语言;而另一部分为了达到比较高的运行效率,则可以用汇编语言编写。较为复杂的软件,一般需要数十种甚至上百种的源代码的参与。为了降低种复杂度,必须引入一种可以描述各个源代码之间联系,并且如何正确编译的系统。在这样的背景下,修订控制系统(RCS)诞生了,并成为研发者对代码修订的必备工具之一。还有另外一种组合:源代码的编写和编译分别在不同的平台上实现,专业术语叫做软件移植。 质量 对于计算机而言,并不存在真正意义上的“好”的源代码;然而作为一个人,好的书写习惯将决定源代码的好坏。源代码是否具有可读性,成为好坏的重要标准。软件文档则是表明可读性的关键。 作用 源代码主要功用有如下2种作用: 生成目标代码,即计算机可以识别的代码。 对软件进行说明,即对软件的编写进行说明。为数不少的初学者,甚至少数有经验的程序员都忽视软件说明的编写,因为这部分虽然不会在生成的程序中直接显示,也不参与编译。但是说明对软件的学习、分享、维护和软件复用都有巨大的好处。因此,书写软件说明在业界被认为是能创造优秀程序的良好习惯,一些公司也硬性规定必须书写。

Spark源码学习(4)——Scheduler

Spark源码学习(4)——Scheduler Scheduler的基本过程 用户提交的Job到DAGScheduler后,会封装成ActiveJob,同时启动JobWaiter监听作业的完成情况。同时依据job中RDD的dependency和dependency属性(窄依赖NarrowDependency,宽依赖ShufflerDependecy),DAGScheduler会根据依赖关系的先后产生出不同的stage DAG(result stage, shuffle map stage)。在每一个stage内部,根据stage产生出相应的task,包括ResultTask或是ShuffleMapTask,这些task会根据RDD中partition的数量和分布,产生出一组相应的task,并将其包装为TaskSet提交到TaskScheduler上去。 DAGScheduler DAGScheduler是高层级别的调度器。实现了stage-oriented调度。它计算一个DAG中stage 的工作。并将这些stage输出落地物化。 最终提交stage以taskSet方式提交给TaskScheduler。DAGScheduler需要接收上下层的消息,它也是一个actor。这里主要看看他的一些事件处理。以下是的所处理的事件。 private[scheduler] case class JobSubmitted( jobId: Int, finalRDD: RDD[_], func: (TaskContext, Iterator[_]) => _, partitions: Array[Int], callSite: CallSite, listener: JobListener, properties: Properties = null) extends DAGSchedulerEvent private[scheduler] case class StageCancelled(stageId: Int) extends DAGSchedulerEvent private[scheduler] case class JobCancelled(jobId: Int) extends DAGSchedulerEvent private[scheduler] case class JobGroupCancelled(groupId: String) extends DAGSchedulerEvent private[scheduler] case object AllJobsCancelled extends DAGSchedulerEvent private[scheduler] case class BeginEvent(task: Task[_], taskInfo: TaskInfo) extends DAGSchedulerEvent private[scheduler] case class GettingResultEvent(taskInfo: TaskInfo) extends DAGSchedulerEvent 还有很多,不一一罗列。

Java面向对象程序设计复习题附答案

Java面向对象程序设计复习题 一、选择题 1、下列哪个是Java中的关键字(C )。 A、run B、Integer C、default D、implement 2、下面关于Java.applet.Applet和其祖先类的描述语句哪个不对(B )。 A、Applet是Container的一种 B、Applet是Window的一种 C、Applet是Component的一种 D、Applet是Panel的一种 3、下列类DataOutputStream的构造方法正确的是(A )。 A、new dataOutputStream(new FileOutputStream(“out.txt”)); B、new dataOutputStream(“out.txt”); C、new dataOutputStream(new writer(“out.txt”)); D、new dataOutputStream(new FileWriter(“out.txt”)); 4、在switch(表达式)语句中,表达式的类型不能为(C )。 A、byte B、char C、long D、int 5、在接口MouseMotionListener中方法正确的是(A )。 A、Public void mouseDragged(MouseEvent) B、Public boolean mouseDragged(MouseEvent) C、Public void mouseDragged(MouseMotionEvent) D、Public boolean MouseDragged(MouseMotionEvent) 6、下面是一些异常类的层次关系 https://www.360docs.net/doc/7e11366008.html,ng.Exception https://www.360docs.net/doc/7e11366008.html,ng.RuntimeException https://www.360docs.net/doc/7e11366008.html,ng.IndexOutOfBoundsException https://www.360docs.net/doc/7e11366008.html,ng.ArrayIndexOutOfBoundsException https://www.360docs.net/doc/7e11366008.html,ng.StringIndexOutOfBoundsException 假设有一个方法X,能够抛出两个异常,Array Index和String Index异常,假定方法X中没有try-catch语句,下面哪个答案是正确的。(B ) A、方法X应该声明抛弃ArrayIndexOutOfBoundsException和StringIndexOutOfBounds Exception。 B、如果调用X的方法捕获IndexOutOfBoundsException,则ArrayIndexOutOfBounds Exception和StringIndexOutOfBoundsException都可以被捕获。 C、如果方法X声明抛弃IndexOutOfBoundsException,则调用X的方法必须用Try-catch 语句 捕获。 D、方法X不能声明抛弃异常。 7、现有一变量声明为boolean aa;下面赋值语句中正确的是( D )。 A、aa=0 B、aa=True C、aa="true" D、aa=false 8、某类Example的main()方法参数为args,当输入数据Java Example cat时,args[0]的值为(A )。 A、cat B、Java C、example D、null 9、String s1=new String(“Java”);String s2=new String(s1)则下列哪个说法是正确的(C )。 A、表达式s1==s2为真 B、s1和s2是同一个对象

Scala从基础到开发实战

Scala从基础到开发实战 对于进化缓慢的Java跟C++语言来说,目前Scala无疑更适应现代化特质的语言,语法简洁,同时兼备函数式编程与面向对象编程,具有令人耳目一新的编程范式。而运行在Java 虚拟机上的编译环境使得其具有很多的现有工具与类库,拥有快速的可靠的解释器和编译器。 本课程是Scala语言基础课程,面向没有或仅有少量编程语言基础的同学,当然,具有一定的Java或C、C++语言基础将有助于本课程的学习。在本课程内,将更注重scala的各种语言规则和应用,通过学习本课程能具备初步的Scala语言实际编程能力。 Scala最近的红火也得益于Spark分布式内存计算平台的兴起,由于其惊人的计算速度,Spark将要革命Hadoop的说法尘嚣日上,但学习Spark的一项瓶颈是其原生语言Scala并不为大众所熟知,即使是资深程序员,从未听说过Scala者大有人在,于是本门课程也可以称为Spark系列的前置课程,供深入学习大数据技术的同仁们进行热身运动。 课程大纲: 第一课:Scala介绍——如何安装Scala REPL、SBT、IDE,编写简单的Scala程序;函数式编程简介 第二课:Scala的class和object,Scala的变量、类的介绍 第三课:Scala的基本数据类型、控制语句 第四课:高阶函数、Currying、尾递归 第五课:数据结构:List、Map、Set 第六课:组合和继承 第七课:Trait 第八课:响应式编程介绍 第九课:Akka框架(一)——akka的基本用法 第十课:Akka框架(二)——actor的监控 第十一课:Akka框架(三)——网络编程 第十二课:Akka框架(四)——akka使用技巧

如何读源代码

如何阅读源代码 --转自CSDN_oncoding +++++++++++ 第一章: 导论 ++++++++++++ 1.要养成一个习惯, 经常花时间阅读别人编写的高品质代码. 2.要有选择地阅读代码, 同时, 还要有自己的目标. 您是想学习新的模式|编码风格|还是满足某些需求的方法. 3.要注意并重视代码中特殊的非功能性需求, 这些需求也许会导致特殊的实现风格. 4.在现有的代码上工作时, 请与作者和维护人员进行必要的协调, 以避免重复劳动或产生厌恶情绪. 5.请将从开放源码软件中得到的益处看作是一项贷款, 尽可能地寻找各种方式来回报开放源码社团. 6.多数情况下, 如果您想要了解"别人会如何完成这个功能呢?", 除了阅读代码以外, 没有更好的方法. 7.在寻找bug时, 请从问题的表现形式到问题的根源来分析代码. 不要沿着不相关的路径(误入歧途). 8.我们要充分利用调试器|编译器给出的警告或输出的符号代码|系统调用跟踪器|数据库结构化查询语言的日志机制|包转储工具和Windows的消息侦查程序, 定出的bug的位置. 9.对于那些大型且组织良好的系统, 您只需要最低限度地了解它的全部功能, 就能够对它做出修改. 10.当向系统中增加新功能时, 首先的任务就是找到实现类似特性的代码, 将它作为待实现功能的模板. 11.从特性的功能描述到代码的实现, 可以按照字符串消息, 或使用关键词来搜索代码. 12.在移植代码或修改接口时, 您可以通过编译器直接定位出问题涉及的范围, 从而减少代码阅读的工作量.

13.进行重构时, 您从一个能够正常工作的系统开始做起, 希望确保结束时系统能够正常工作. 一套恰当的测试用例(test case)可以帮助您满足此项约束. 14.阅读代码寻找重构机会时, 先从系统的构架开始, 然后逐步细化, 能够获得最大的效益. 15.代码的可重用性是一个很诱人, 但难以理解与分离, 可以试着寻找粒度更大一些的包, 甚至其他代码. 16.在复查软件系统时, 要注意, 系统是由很多部分组成的, 不仅仅只是执行语句. 还要注意分析以下内容: 文件和目录结构|生成和配置过程|用户界面和系统的文档. 18.可以将软件复查作为一个学习|讲授|援之以手和接受帮助的机会. ++++++++++++++++++++ 第二章: 基本编程元素 ++++++++++++++++++++ 19.第一次分析一个程序时, main是一个好的起始点. 20.层叠if-else if-...-else序列可以看作是由互斥选择项组成的选择结构. 21.有时, 要想了解程序在某一方面的功能, 运行它可能比阅读源代码更为恰当. 22.在分析重要的程序时, 最好首先识别出重要的组成部分. 23.了解局部的命名约定, 利用它们来猜测变量和函数的功能用途. 24.当基于猜测修改代码时, 您应该设计能够验证最初假设的过程. 这个过程可能包括用编译器进行检查|引入断言|或者执行适当的测试用例. 25.理解了代码的某一部分, 可能帮助你理解余下的代码. 26.解决困难的代码要从容易的部分入手. 27.要养成遇到库元素就去阅读相关文档的习惯; 这将会增强您阅读和编写代码的能力. 28.代码阅读有许多可选择的策略: 自底向上和自顶向下的分析|应用试探法和检查注释和外部文档, 应该依据问题的需要尝试所有这些方法. 29.for (i=0; i

大数据开发新手学习指南(经典)

上市公司,官网:https://www.360docs.net/doc/7e11366008.html, 大数据开发初学者该如何学习 导读: 第一章:初识Hadoop 第二章:更高效的WordCount 第三章:把别处的数据搞到Hadoop上 第四章:把Hadoop上的数据搞到别处去 第五章:快一点吧,我的SQL 第六章:一夫多妻制 第七章:越来越多的分析任务 第八章:我的数据要实时 第九章:我的数据要对外 第十章:牛逼高大上的机器学习 经常有初学者会问,自己想往大数据方向发展,该学哪些技术,学习路线是什么样的,觉得大数据很火,就业很好,薪资很高……首先,如果你确定了想往这个方面发展,先考虑自己的过去从业经历、专业、兴趣是什么。计算机专业——操作系统、硬件、网络、服务器?软件专业——软件开发、编程、写代码?还是数学、统计学专业——对数据和数字特别感兴趣? 其实这就是想告诉你大数据的三个发展方向,平台搭建/优化/运维/监控、大数据开发/设计/架构、数据分析/挖掘。 先扯一下大数据的4V特征: ?数据量大,TB->PB ?数据类型繁多,结构化、非结构化文本、日志、视频、图片、地理位置等;

上市公司,官网:https://www.360docs.net/doc/7e11366008.html, ?商业价值高,但是这种价值需要在海量数据之上,通过数据分析与机器学习更快速的挖掘出来; ?处理时效性高,海量数据的处理需求不再局限在离线计算当中。 现如今,正式为了应对大数据的这几个特点,开源的大数据框架越来越多,越来越强,先列举一些常见的: 文件存储:Hadoop HDFS、Tachyon、KFS 离线计算:Hadoop MapReduce、Spark 流式、实时计算:Storm、Spark Streaming、S4、Heron K-V、NOSQL数据库:HBase、Redis、MongoDB 资源管理:YARN、Mesos 日志收集:Flume、Scribe、Logstash、Kibana 消息系统:Kafka、StormMQ、ZeroMQ、RabbitMQ 查询分析:Hive、Impala、Pig、Presto、Phoenix、SparkSQL、Drill、Flink、Kylin、Druid 分布式协调服务:Zookeeper 集群管理与监控:Ambari、Ganglia、Nagios、Cloudera Manager 数据挖掘、机器学习:Mahout、Spark MLLib 数据同步:Sqoop 任务调度:Oozie 1.1 学会百度与Google

如何看懂源代码--(分析源代码方法)

如何看懂源代码--(分析源代码方法) 4 推 荐 由于今日计划着要看Struts 开源框架的源代码 昨天看了一个小时稍微有点头绪,可是这个速度本人表示非常不满意,先去找了下资 料, 觉得不错... 摘自(繁体中文 Traditional Chinese):http://203.208.39.132/translate_c?hl=zh-CN&sl=en&tl=zh-CN&u=http://ww https://www.360docs.net/doc/7e11366008.html,/itadm/article.php%3Fc%3D47717&prev=hp&rurl=https://www.360docs.net/doc/7e11366008.html,&usg=AL kJrhh4NPO-l6S3OZZlc5hOcEQGQ0nwKA 下文为经过Google翻译过的简体中文版: 我们在写程式时,有不少时间都是在看别人的代码。 例如看小组的代码,看小组整合的守则,若一开始没规划怎么看,就会“噜看噜苦(台语)”不管是参考也好,从开源抓下来研究也好,为了了解箇中含意,在有限的时间下,不免会对庞大的源代码解读感到压力。网路上有一篇关于分析看代码的方法,做为程式设计师的您,不妨参考看看,换个角度来分析。也能更有效率的解读你想要的程式码片段。 六个章节: ( 1 )读懂程式码,使心法皆为我所用。( 2 )摸清架构,便可轻松掌握全貌。( 3 )优质工具在手,读懂程式非难事。( 4 )望文生义,进而推敲组件的作用。( 5 )找到程式入口,再由上而下抽丝剥茧。( 6 )阅读的乐趣,透过程式码认识作者。 程式码是别人写的,只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程式码。但是,与其抗拒接收别人的程式码,不如彻底了解相关的语言和惯例,当成是培养自我实力的基石。 对大多数的程式人来说,撰写程式码或许是令人开心的一件事情,但我相信,有更多人视阅读他人所写成的程式码为畏途。许多人宁可自己重新写过一遍程式码,也不愿意接收别人的程式码,进而修正错误,维护它们,甚至加强功能。 这其中的关键究竟在何处呢?若是一语道破,其实也很简单,程式码是别人写的,只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程式码。这是来自于人类内心深处对于陌生事物的原始恐惧。 读懂别人写的程式码,让你收获满满 不过,基于许多现实的原因,程式人时常受迫要去接收别人的程式码。例如,同事离职了,必须接手他遗留下来的工作,也有可能你是刚进部门的菜鸟,而同事经验值够了,升级了,风水轮流转,一代菜鸟换菜鸟。甚至,你的公司所承接的专案,必须接手或是整合客户前一个厂商所遗留下来的系统,你们手上只有那套系统的原始码(运气好时,还有数量不等的文件)。 诸如此类的故事,其实时常在程式人身边或身上持续上演着。许多程式人都将接手他人的程式码,当做一件悲惨的事情。每个人都不想接手别人所撰写的程式码,因为不想花时间去探索,宁可将生产力花在产生新的程式码,而不是耗费在了解这些程式码上。

用Apache Spark进行大数据处理——第一部分:入门介绍

用Apache Spark进行大数据处理——第一部分:入门介绍 什么是Spark Apache Spark是一个围绕速度、易用性和复杂分析构建的大数据处理框架。最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apache的开源项目之一。与Hadoop和Storm等其他大数据和MapReduce技术相比,Spark有如下优势。 首先,Spark为我们提供了一个全面、统一的框架用于管理各种有着不同性质(文本数据、图表数据等)的数据集和数据源(批量数据或实时的流数据)的大数据处理的需求。 Spark可以将Hadoop集群中的应用在内存中的运行速度提升100倍,甚至能够将应用在磁盘上的运行速度提升10倍。 Spark让开发者可以快速的用Java、Scala或Python编写程序。它本身自带了一个超过80个高阶操作符集合。而且还可以用它在shell中以交互式地查询数据。 除了Map和Reduce操作之外,它还支持SQL查询,流数据,机器学习和图表数据处理。开发者可以在一个数据管道用例中单独使用某一能力或者将这些能力结合在一起使用。 在这个Apache Spark文章系列的第一部分中,我们将了解到什么是Spark,它与典型的MapReduce解决方案的比较以及它如何为大数据处理提供了一套完整的工具。 Hadoop和Spark Hadoop这项大数据处理技术大概已有十年历史,而且被看做是首选的大数据集合处理的解决方案。MapReduce是一路计算的优秀解决方案,不过对于需要多路计算和算法的用例来说,并非十分高效。数据处理流程中的每一步都需要一个Map阶段和一个Reduce阶段,而且如果要利用这一解决方案,需要将所有用例都转换成MapReduce模式。 在下一步开始之前,上一步的作业输出数据必须要存储到分布式文件系统中。因此,复制和磁盘存储会导致这种方式速度变慢。另外Hadoop解决方案中通常会包含难以安装和管理的集群。而且为了处理不同的大数据用例,还需要集成多种不同的工具(如用于机器学习的Mahout和流数据处理的Storm)。 如果想要完成比较复杂的工作,就必须将一系列的MapReduce作业串联起来然后顺序执行这些作业。每一个作业都是高时延的,而且只有在前一个作业完成之后下一个作业才能开始启动。 而Spark则允许程序开发者使用有向无环图(DAG)开发复杂的多步数据管道。而且还支持跨有向无环图的内存数据共享,以便不同的作业可以共同处理同一个数据。

Spark开发环境配置及流程(Intellij IDEA)

Spark开发环境配置及流程 之前已经将集群配置完成(详见Hadoop2.6.0搭建过程.doc和Spark1.2搭建过程.doc文档),开发环境中的JDK,Scala部分就不介绍了,下面直接介绍我们用的开发工具Interlij IDEA。为什么选择Intellij IDEA?因为它更好的支持Scala 项目,目前Spark开发团队使用它作为开发环境。 1.下载 直接到官方网站下载页面下载(https://www.360docs.net/doc/7e11366008.html,/idea/download/)。 有收费的完整版,也有免费的基本版本,收费的网上也有破解方案。 2.解压 解压到/usr/local,这是因为之前的Scala和Spark都放这里,也可以根据自己喜好。 [hadoop@lenovo0 Downloads]$ sudo tar -vxzf ideaIC-14.1.tar.gz -C /usr/local/ 改个名字,然后授权给hadoop用户。 [hadoop@lenovo0 local]$ cd /usr/local/ [hadoop@lenovo0 local]$ sudo mv ideaIC-14.1 ideaIC14 [hadoop@lenovo0 local]$ sudo chown -R hadoop:hadoop ideaIC14/ 3.启动 在解压的文件夹下有个文件介绍怎么打开应用,还有一些设置信息,大家可以看一看: 通过cat命令可以查看,我只截了一些关键的:

根据提示,我们直接进入到文件夹bin目录下执行./idea.sh即可启动: 之后便可以根据UI提示界面创建快捷方式,方便下次启动。 4.在IDEA中安装Scala插件 在IDEA的设置里面,直接搜索“plugins”,在右边的展开中搜索“scala”,点击相应的按钮添加插件即可: 5.配置Spark应用开发环境 这里以SparkPi程序为例子。 5.1创建Scala Project,设置名称,JDK和Scala路径:

相关文档
最新文档