﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Feeling</title><link>http://www.blogjava.net/cnfree/</link><description>　　　　三人行，必有我师焉</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 06:32:15 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 06:32:15 GMT</pubDate><ttl>60</ttl><item><title>怎么一键批量删除PDF中的图片水印？</title><link>http://www.blogjava.net/cnfree/archive/2021/03/09/435819.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Tue, 09 Mar 2021 12:29:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2021/03/09/435819.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/435819.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2021/03/09/435819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/435819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/435819.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 很多网上下载的PDF文件都包含各种形式的水印，本文主要阐述如何使用易转换一键删除PDF文件中的各种图片水印和文字水印&nbsp;&nbsp;<a href='http://www.blogjava.net/cnfree/archive/2021/03/09/435819.html'>阅读全文</a><img src ="http://www.blogjava.net/cnfree/aggbug/435819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2021-03-09 20:29 <a href="http://www.blogjava.net/cnfree/archive/2021/03/09/435819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】使用Scala IDE编译Spark源代码</title><link>http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Tue, 08 Nov 2016 05:12:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/431965.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/431965.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/431965.html</trackback:ping><description><![CDATA[Spark源代码下载地址： <a href="http://spark.apache.org/downloads.html">http://spark.apache.org/downloads.html</a><br />
<br />
下载后，直接用 Scala IDE 通过已存在的项目导入到Eclipse workspace中去，然后Eclipse会自动进行编译。第一次编译会报很多错误，不过总的来说，导致编译错误的源头有三个：<br />
1、Scala编译器版本错误<br />
2、Eclipse Maven插件不能自动识别spark project的一些pom，报Plugin execution not covered by lifecycle configuration异常<br />
3、一些项目，maven会自动生成scala和java文件，但是这些自动生成的代码文件没有配置在eclipse项目的classpath里。<br />
<br />
针对第一种错误，比较简单，对于每个scala项目，右键属性选择spark对应的scala编译器版本。<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/scala_compiler.png" border="0" alt="" /><br />
<br />
当然spark代码里的项目有几十个，只能手工一个个设置了，比较傻，没办法，还不停的弹出对话框，不停地回车吧。<br />
<br />
编译的难点主要在第二种错误上，比如spark-sql项目的pom, 里面有个build-helper-maven-plugin，它下面的execution，eclipse maven插件无法识别，报Plugin execution not covered by lifecycle configuration异常，解决方案参见 <a href="https://www.eclipse.org/m2e/documentation/m2e-execution-not-covered.html">https://www.eclipse.org/m2e/documentation/m2e-execution-not-covered.html</a>，先使用 Eclipse&nbsp;<span style="color: #555555; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 15px; line-height: 24px; background-color: #ffffff;">quick-fix选项自动修复，忽略此 maven goal，Eclipse 会为 pom.xml自动添加一段xml代码，包含在&nbsp;</span>pluginManagement section中，里面有一段 &lt;action&gt;&lt;ignore/&gt;&lt;/action&gt;，此处手动修改成<br />
<div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">action</span><span style="color: #0000FF; ">&gt;</span><br />
&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">execute</span><span style="color: #0000FF; ">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">runOnIncremental</span><span style="color: #0000FF; ">&gt;</span>false<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">runOnIncremental</span><span style="color: #0000FF; ">&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">execute</span><span style="color: #0000FF; ">&gt;</span><br />
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000; ">action</span><span style="color: #0000FF; ">&gt;</span></div>
然后右键 maven update project 就OK了。<br />
<br />
一共有5个project需要修改pom，如图<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/pom.png" border="0" alt="" /><br />
<br />
修改pom后重新编译，依旧会报一些错误，这些错误都是由于maven自动生成的java和scala代码没有添加到classpath里导致的编译错误，只需要手工添加一下即可，需要手工添加项目有 spark-streaming-flume-sink 的 src_managed\main\compiled_avro 目录 和 spark-sql 项目的 test\gen-java 目录。<br />
<br />
全部编译好以后的截图：<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/spark.png" width="311" height="700" alt="" /><br /><br />修改完以后，Spark代码全部编译下来大概耗时25分钟左右（CPU 双核 I7 4600）<br /><br />原文地址：<a id="Editor_Edit_hlEntryLink" title="view: 【原创】使用Scala IDE编译Spark源代码" href="http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html" target="_blank" style="color: #002c99; text-decoration: none; font-family: arial; font-size: 12px; line-height: normal; background-image: inherit; background-attachment: inherit; background-color: #ffffff; background-size: inherit; background-origin: inherit; background-clip: inherit; background-position: inherit; background-repeat: inherit;">http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html</a><img src ="http://www.blogjava.net/cnfree/aggbug/431965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2016-11-08 13:12 <a href="http://www.blogjava.net/cnfree/archive/2016/11/08/431965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Spark知识体系完整解读</title><link>http://www.blogjava.net/cnfree/archive/2016/09/08/431774.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Thu, 08 Sep 2016 05:11:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2016/09/08/431774.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/431774.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2016/09/08/431774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/431774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/431774.html</trackback:ping><description><![CDATA[<p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">Spark简介</span></strong></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Spark是整个BDAS的核心组件，是一个大数据分布式编程框架，不仅实现了MapReduce的算子map 函数和reduce函数及计算模型，还提供更为丰富的算子，如filter、join、groupByKey等。是一个用来实现快速而同用的集群计算的平台。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Spark将分布式数据抽象为弹性分布式数据集（RDD），实现了应用任务调度、RPC、序列化和压缩，并为运行在其上的上层组件提供API。其底层采用Scala这种函数式语言书写而成，并且所提供的API深度借鉴Scala函数式的编程思想，提供与Scala类似的编程接口</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;"><strong style="border: 0px; margin: 0px; padding: 0px;">Sparkon Yarn</strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/b6fc307323e9498785a2651633dbc135_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;">从用户提交作业到作业运行结束整个运行期间的过程分析。</span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;">一、客户端进行操作</strong></span></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">根据yarnConf来初始化yarnClient，并启动yarnClient</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">创建客户端Application，并获取Application的ID，进一步判断集群中的资源是否满足executor和ApplicationMaster申请的资源，如果不满足则抛出IllegalArgumentException；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">设置资源、环境变量：其中包括了设置Application的Staging目录、准备本地资源（jar文件、log4j.properties）、设置Application其中的环境变量、创建Container启动的Context等；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">设置Application提交的Context，包括设置应用的名字、队列、AM的申请的Container、标记该作业的类型为Spark；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">申请Memory，并最终通过yarnClient.submitApplication向ResourceManager提交该Application。</span></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;">当作业提交到YARN上之后，客户端就没事了，甚至在终端关掉那个进程也没事，因为整个作业运行在YARN集群上进行，运行的结果将会保存到HDFS或者日志中。</span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;">二、提交到YARN集群，YARN操作</strong></span></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">运行ApplicationMaster的run方法；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">设置好相关的环境变量。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">创建amClient，并启动；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">在Spark UI启动之前设置Spark UI的AmIpFilter；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">在startUserClass函数专门启动了一个线程（名称为Driver的线程）来启动用户提交的Application，也就是启动了Driver。在Driver中将会初始化SparkContext；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">等待SparkContext初始化完成，最多等待spark.yarn.applicationMaster.waitTries次数（默认为10），如果等待了的次数超过了配置的，程序将会退出；否则用SparkContext初始化yarnAllocator；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">当SparkContext、Driver初始化完成的时候，通过amClient向ResourceManager注册ApplicationMaster</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">分配并启动Executeors。在启动Executeors之前，先要通过yarnAllocator获取到numExecutors个Container，然后在Container中启动Executeors。</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">那么这个Application将失败，将Application Status标明为FAILED，并将关闭SparkContext。其实，启动Executeors是通过ExecutorRunnable实现的，而ExecutorRunnable内部是启动CoarseGrainedExecutorBackend的。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">最后，Task将在CoarseGrainedExecutorBackend里面运行，然后运行状况会通过Akka通知CoarseGrainedScheduler，直到作业运行完成。</span></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;"><strong style="border: 0px; margin: 0px; padding: 0px;">Spark节点的概念</strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;">一、Spark驱动器是执行程序中的main()方法的进程。</strong></span>它执行用户编写的用来创建SparkContext(初始化)、创建RDD，以及运行RDD的转化操作和行动操作的代码。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;">驱动器节点driver的职责：</span></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">把用户程序转为任务task(driver)</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　Spark驱动器程序负责把用户程序转化为多个物理执行单元，这些单元也被称之为任务task(详解见备注)</p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">为执行器节点调度任务(executor)</span></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　有了物理计划之后，Spark驱动器在各个执行器节点进程间协调任务的调度。Spark驱动器程序会根据当前的执行器节点，把所有任务基于数据所在位置分配给合适的执行器进程。当执行任务时，执行器进程会把缓存的数据存储起来，而驱动器进程同样会跟踪这些缓存数据的位置，并利用这些位置信息来调度以后的任务，以尽量减少数据的网络传输。（就是所谓的移动计算，而不移动数据)。</p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;">二、执行器节点</strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　作用：</p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">负责运行组成Spark应用的任务，并将结果返回给驱动器进程；</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">通过自身的块管理器(blockManager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在执行器进程内的，因此任务可以在运行时充分利用缓存数据加快运算。</span></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　驱动器的职责：</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　所有的Spark程序都遵循同样的结构：程序从输入数据创建一系列RDD，再使用转化操作派生成新的RDD，最后使用行动操作手机或存储结果RDD，Spark程序其实是隐式地创建出了一个由操作组成的逻辑上的有向无环图DAG。当驱动器程序执行时，它会把这个逻辑图转为物理执行计划。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　这样 Spark就把逻辑计划转为一系列步骤(stage)，而每个步骤又由多个任务组成。这些任务会被打包送到集群中。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">Spark初始化</span></strong></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">每个Spark应用都由一个驱动器程序来发起集群上的各种并行操作。驱动器程序包含应用的main函数，并且定义了集群上的分布式数据集，以及对该分布式数据集应用了相关操作。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">驱动器程序通过一个SparkContext对象来访问spark,这个对象代表对计算集群的一个连接。（比如在sparkshell启动时已经自动创建了一个SparkContext对象，是一个叫做SC的变量。(下图，查看变量sc)</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<img src="http://img.mp.itc.cn/upload/20160523/e84eb1ecb347402cbc4fe7c3a1490cca.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">一旦创建了sparkContext，就可以用它来创建RDD。比如调用sc.textFile()来创建一个代表文本中各行文本的RDD。（比如vallinesRDD = sc.textFile(&#8220;yangsy.text&#8221;),val spark = linesRDD.filter(line=&gt;line.contains(&#8220;spark&#8221;),spark.count()）</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">执行这些操作，驱动器程序一般要管理多个执行器,就是我们所说的executor节点。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">在初始化SparkContext的同时，加载sparkConf对象来加载集群的配置，从而创建sparkContext对象。</span></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">从源码中可以看到，在启动thriftserver时，调用了spark- daemon.sh文件，该文件源码如左图，加载spark_home下的conf中的文件。</span></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　<img src="http://img.mp.itc.cn/upload/20160523/9c8c43b1175c4c9cb5aca38a1651a383_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">（在执行后台代码时，需要首先创建conf对象，加载相应参数， val sparkConf = newSparkConf().setMaster("local").setAppName("cocapp").set("spark.executor.memory","1g"), val sc: SparkContext = new SparkContext(sparkConf))</span></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;"><strong style="border: 0px; margin: 0px; padding: 0px;">RDD工作原理：</strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　RDD(Resilient DistributedDatasets)[1] ,弹性分布式数据集，是分布式内存的一个抽象概念，RDD提供了一种高度受限的共享内存模型，即RDD是只读的记录分区的集合，只能通过在其他RDD执行确定的转换操作（如map、join和group by）而创建，然而这些限制使得实现容错的开销很低。对开发者而言，RDD可以看作是Spark的一个对象，它本身运行于内存中，如读文件是一个RDD，对文件计算是一个RDD，结果集也是一个RDD ，不同的分片、数据之间的依赖、key-value类型的map数据都可以看做RDD。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　主要分为三部分：创建RDD对象，DAG调度器创建执行计划，Task调度器分配任务并调度Worker开始运行。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　SparkContext(RDD相关操作)&#8594;通过(提交作业)&#8594;(遍历RDD拆分stage&#8594;生成作业)DAGScheduler&#8594;通过（提交任务集）&#8594;任务调度管理(TaskScheduler)&#8594;通过（按照资源获取任务)&#8594;任务调度管理(TaskSetManager)</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Transformation返回值还是一个RDD。它使用了链式调用的设计模式，对一个RDD进行计算后，变换成另外一个RDD，然后这个RDD又可以进行另外一次转换。这个过程是分布式的。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Action返回值不是一个RDD。它要么是一个Scala的普通集合，要么是一个值，要么是空，最终或返回到Driver程序，或把RDD写入到文件系统中</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　转换(Transformations)(如：map, filter, groupBy, join等)，Transformations操作是Lazy的，也就是说从一个RDD转换生成另一个RDD的操作不是马上执行，Spark在遇到Transformations操作时只会记录需要这样的操作，并不会去执行，需要等到有Actions操作的时候才会真正启动计算过程进行计算。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　操作(Actions)(如：count, collect, save等)，Actions操作会返回结果或把RDD数据写到存储系统中。Actions是触发Spark启动计算的动因。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　它们本质区别是：Transformation返回值还是一个RDD。它使用了链式调用的设计模式，对一个RDD进行计算后，变换成另外一个RDD，然后这个RDD又可以进行另外一次转换。这个过程是分布式的。Action返回值不是一个RDD。它要么是一个Scala的普通集合，要么是一个值，要么是空，最终或返回到Driver程序，或把RDD写入到文件系统中。关于这两个动作，在Spark开发指南中会有就进一步的详细介绍，它们是基于Spark开发的核心。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">RDD基础</span></strong></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">Spark中的RDD就是一个不可变的分布式对象集合。每个RDD都被分为多个分区，这些分区运行在集群的不同节点上。创建RDD的方法有两种：一种是读取一个外部数据集；一种是在群东程序里分发驱动器程序中的对象集合，不如刚才的示例，读取文本文件作为一个字符串的RDD的示例。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">创建出来后，RDD支持两种类型的操作:转化操作和行动操作</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">转化操作会由一个RDD生成一个新的RDD。（比如刚才的根据谓词筛选）</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">行动操作会对RDD计算出一个结果，并把结果返回到驱动器程序中，或把结果存储到外部存储系统（比如HDFS）中。比如first()操作就是一个行动操作，会返回RDD的第一个元素。</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">注：转化操作与行动操作的区别在于Spark计算RDD的方式不同。虽然你可以在任何时候定义一个新的RDD，但Spark只会惰性计算这些RDD。它们只有第一个在一个行动操作中用到时，才会真正的计算。之所以这样设计，是因为比如刚才调用sc.textFile(...)时就把文件中的所有行都读取并存储起来，就会消耗很多存储空间，而我们马上又要筛选掉其中的很多数据。</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">这里还需要注意的一点是，spark会在你每次对它们进行行动操作时重新计算。如果想在多个行动操作中重用同一个RDD，那么可以使用RDD.persist()或RDD.collect()让Spark把这个RDD缓存下来。（可以是内存，也可以是磁盘)</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">Spark会使用谱系图来记录这些不同RDD之间的依赖关系，Spark需要用这些信息来按需计算每个RDD，也可以依靠谱系图在持久化的RDD丢失部分数据时用来恢复所丢失的数据。(如下图，过滤errorsRDD与warningsRDD,最终调用union()函数)</span></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　<img src="http://img.mp.itc.cn/upload/20160523/97757ec3b2ab4d56b0942b96e300c71d.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">RDD计算方式</span></strong></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/06d3d32ab45742e68e7683672f6a46a5_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;">RDD的宽窄依赖</strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/c8c6f04edfc14bb79dffd997e1de2e5a_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　窄依赖 (narrowdependencies) 和宽依赖 (widedependencies) 。窄依赖是指 父 RDD 的每个分区都只被子 RDD 的一个分区所使用 。相应的，那么宽依赖就是指父 RDD 的分区被多个子 RDD 的分区所依赖。例如， map 就是一种窄依赖，而 join 则会导致宽依赖</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　这种划分有两个用处。首先，窄依赖支持在一个结点上管道化执行。例如基于一对一的关系，可以在 filter 之后执行 map 。其次，窄依赖支持更高效的故障还原。因为对于窄依赖，只有丢失的父 RDD 的分区需要重新计算。而对于宽依赖，一个结点的故障可能导致来自所有父 RDD 的分区丢失，因此就需要完全重新执行。因此对于宽依赖，Spark 会在持有各个父分区的结点上，将中间数据持久化来简化故障还原，就像 MapReduce 会持久化 map 的输出一样。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">SparkExample</span></strong></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/e3694ef692b44e1f95432de5ed8416bc.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;">步骤 1 ：创建 RDD 。</strong>上面的例子除去最后一个 collect 是个动作，不会创建 RDD 之外，前面四个转换都会创建出新的 RDD 。因此第一步就是创建好所有 RDD( 内部的五项信息 ) 。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;">步骤 2 ：创建执行计划。</strong>Spark 会尽可能地管道化，并基于是否要重新组织数据来划分 阶段 (stage) ，例如本例中的 groupBy() 转换就会将整个执行计划划分成两阶段执行。最终会产生一个 DAG(directedacyclic graph ，有向无环图 ) 作为逻辑执行计划。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;">步骤 3 ：调度任务。&nbsp;</strong>将各阶段划分成不同的 任务 (task) ，每个任务都是数据和计算的合体。在进行下一阶段前，当前阶段的所有任务都要执行完成。因为下一阶段的第一个转换一定是重新组织数据的，所以必须等当前阶段所有结果数据都计算出来了才能继续。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　假设本例中的 hdfs://names 下有四个文件块，那么 HadoopRDD 中 partitions 就会有四个分区对应这四个块数据，同时 preferedLocations 会指明这四个块的最佳位置。现在，就可以创建出四个任务，并调度到合适的集群结点上。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">Spark数据分区</span></strong></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">Spark的特性是对数据集在节点间的分区进行控制。在分布式系统中，通讯的代价是巨大的，控制数据分布以获得最少的网络传输可以极大地提升整体性能。Spark程序可以通过控制RDD分区方式来减少通讯的开销。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">Spark中所有的键值对RDD都可以进行分区。确保同一组的键出现在同一个节点上。比如，使用哈希分区将一个RDD分成了100个分区，此时键的哈希值对100取模的结果相同的记录会被放在一个节点上。</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　<span style="border: 0px; margin: 0px; padding: 0px;">（可使用partitionBy(newHashPartitioner(100)).persist()来构造100个分区)</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">Spark中的许多操作都引入了将数据根据键跨界点进行混洗的过程。(比如：join(),leftOuterJoin(),groupByKey(),reducebyKey()等)对于像reduceByKey()这样只作用于单个RDD的操作，运行在未分区的RDD上的时候会导致每个键的所有对应值都在每台机器上进行本地计算。</span></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">SparkSQL的shuffle过程</span></strong></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/511ccf9cf53e4991a7ac7660dea148ed_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Spark SQL的核心是把已有的RDD，带上Schema信息，然后注册成类似sql里的&#8221;Table&#8221;，对其进行sql查询。这里面主要分两部分，一是生成SchemaRD，二是执行查询。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　如果是spark-hive项目，那么读取metadata信息作为Schema、读取hdfs上数据的过程交给Hive完成，然后根据这俩部分生成SchemaRDD，在HiveContext下进行hql()查询。</p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">SparkSQL结构化数据</span></strong></p><ol style="border: 0px; margin: 26px 0px 0px 30px; padding: 0px; color: #333333; font-family: 微软雅黑, 宋体; line-height: 26px;"><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">首先说一下ApacheHive，Hive可以在HDFS内或者在其他存储系统上存储多种格式的表。SparkSQL可以读取Hive支持的任何表。要把Spark SQL连接已有的hive上，需要提供Hive的配置文件。hive-site.xml文件复制到spark的conf文件夹下。再创建出HiveContext对象(sparksql的入口)，然后就可以使用HQL来对表进行查询，并以由行足证的RDD的形式拿到返回的数据。</span></p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">创建Hivecontext并查询数据</span></p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　importorg.apache.spark.sql.hive.HiveContext</p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　valhiveCtx = new org.apache.spark.sql.hive.HiveContext(sc)</p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　valrows = hiveCtx.sql(&#8220;SELECT name,age FROM users&#8221;)</p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　valfitstRow &#8211; rows.first()</p><p style="border: 0px; margin: 0px; padding: 0px 0px 8px; word-wrap: break-word;">　　println(fitstRow.getSgtring(0)) //字段0是name字段</p></li><li style="border: 0px; margin: 0px; padding: 0px;"><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;"><span style="border: 0px; margin: 0px; padding: 0px;">通过jdbc连接外部数据源更新与加载</span></p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　Class.forName("com.mysql.jdbc.Driver")</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　val conn =DriverManager.getConnection(mySQLUrl)</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　val stat1 =conn.createStatement()</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　stat1.execute("UPDATE CI_LABEL_INFO set DATA_STATUS_ID = 2 , DATA_DATE ='" + dataDate +"' where LABEL_ID in ("+allCreatedLabels.mkString(",")+")")</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　stat1.close()</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　//加载外部数据源数据到内存</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　valDIM_COC_INDEX_MODEL_TABLE_CONF =sqlContext.jdbc(mySQLUrl,"DIM_COC_INDEX_MODEL_TABLE_CONF").cache()</p><p style="border: 0px; margin: 0px; padding: 0px; word-wrap: break-word;">　　val targets =DIM_COC_INDEX_MODEL_TABLE_CONF.filter("TABLE_DATA_CYCLE ="+TABLE_DATA_CYCLE).collect<strong style="border: 0px; margin: 0px; padding: 0px;"></strong></p></li></ol><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;"><strong style="border: 0px; margin: 0px; padding: 0px;"><span style="border: 0px; margin: 0px; padding: 0px; font-size: 16px;">SparkSQL解析</span></strong></span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<img src="http://img.mp.itc.cn/upload/20160523/3e5dbd8210ff4706906ba3609883f9b3_th.jpg" alt="" style="border: 0px; margin: 0px; padding: 0px; font-size: 0px; color: transparent; max-width: 600px;" /></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　<span style="border: 0px; margin: 0px; padding: 0px;">首先说下传统数据库的解析，传统数据库的解析过程是按Rusult、Data Source、Operation的次序来解析的。传统数据库先将读入的SQL语句进行解析，分辨出SQL语句中哪些词是关键字（如select,from,where)，哪些是表达式，哪些是Projection，哪些是Data Source等等。进一步判断SQL语句是否规范，不规范就报错，规范则按照下一步过程绑定（Bind)。过程绑定是将SQL语句和数据库的数据字典(列,表,视图等）进行绑定，如果相关的Projection、Data Source等都存在，就表示这个SQL语句是可以执行的。在执行过程中，有时候甚至不需要读取物理表就可以返回结果，比如重新运行刚运行过的SQL语句，直接从数据库的缓冲池中获取返回结果。在数据库解析的过程中SQL语句时，将会把SQL语句转化成一个树形结构来进行处理，会形成一个或含有多个节点(TreeNode)的Tree,然后再后续的处理政对该Tree进行一系列的操作。</span></p><p style="border: 0px; margin: 0px; padding: 26px 0px 0px; color: #333333; word-wrap: break-word; font-family: 微软雅黑, 宋体; line-height: 26px;">　　Spark SQL对SQL语句的处理和关系数据库对SQL语句的解析采用了类似的方法，首先会将SQL语句进行解析，然后形成一个Tree，后续如绑定、优化等处理过程都是对Tree的操作，而操作方法是采用Rule,通过模式匹配，对不同类型的节点采用不同的操作。SparkSQL有两个分支，sqlContext和hiveContext。sqlContext现在只支持SQL语法解析器（Catalyst)，hiveContext支持SQL语法和HiveContext语法解析器。<br /><br />原文地址：<span style="font-family: verdana, &quot;courier new&quot;; line-height: 21px;">http://mt.sohu.com/20160522/n450849016.shtml</span></p><img src ="http://www.blogjava.net/cnfree/aggbug/431774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2016-09-08 13:11 <a href="http://www.blogjava.net/cnfree/archive/2016/09/08/431774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：spark通过合理设置spark.default.parallelism参数提高执行效率</title><link>http://www.blogjava.net/cnfree/archive/2016/09/08/431773.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Thu, 08 Sep 2016 05:07:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2016/09/08/431773.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/431773.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2016/09/08/431773.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/431773.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/431773.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">spark中有partition的概念（和slice是同一个概念，在spark1.2中官网已经做出了说明），一般每个partition对应一个task。在我的测试过程中，如果没有设置spark.default.parallelism参数，spark计算出来的partition非常巨大，与我的cores非常不搭。我在两台机器上（8cores *2 +6g * 2）上，spark计算出来的partition达到2.8万个，也就是2.9万个tasks，每个task完成时间都是几毫秒或者零点几毫秒，执行起来非常缓慢。在我尝试设置了 spark.default.parallelism&nbsp;后，任务数减少到10，执行一次计算过程从minute降到20second。</p>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">参数可以通过spark_home/conf/spark-default.conf配置文件设置。</p>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">eg.</p>
<div style="margin: 5px 0px; font-size: 12px; line-height: 21.6px;">
<pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: &quot;Courier New&quot; !important;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->spark.master&nbsp;                 spark:<span style="color: #008000; ">//</span><span style="color: #008000; ">master:7077&nbsp;</span><span style="color: #008000; "><br /></span><br />spark.<span style="color: #0000FF; ">default</span>.parallelism&nbsp;    10&nbsp;<br /><br />spark.driver.memory&nbsp;          2g&nbsp;<br /><br />spark.serializer&nbsp;             org.apache.spark.serializer.KryoSerializer&nbsp;<br /><br />spark.sql.shuffle.partitions&nbsp; 50</div></pre>
</div>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">&nbsp;</p>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">下面是官网的相关描述：</p>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">from:<a href="http://spark.apache.org/docs/latest/configuration.html" target="_blank" style="margin: 0px; padding: 0px; color: #000000;">http://spark.apache.org/docs/latest/configuration.html</a></p>
<table style="margin: 0px; padding: 0px; border-collapse: collapse; border-spacing: 0px; border-style: solid; border-color: silver; word-break: break-word; color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">
     <tbody style="margin: 0px; padding: 0px;">
         <tr style="margin: 0px; padding: 0px;">
             <th style="margin: 0px; padding: 3px; border: 1px solid silver; border-collapse: collapse;">Property Name</th><th style="margin: 0px; padding: 3px; border: 1px solid silver; border-collapse: collapse;">Default</th><th style="margin: 0px; padding: 3px; border: 1px solid silver; border-collapse: collapse;">Meaning</th>
         </tr>
         <tr style="margin: 0px; padding: 0px;">
             <td style="margin: 0px; padding: 3px; border-style: solid; border-color: silver; border-collapse: collapse;"><code style="margin: 0px; padding: 0px;">spark.default.parallelism</code></td>
             <td style="margin: 0px; padding: 3px; border-style: solid; border-color: silver; border-collapse: collapse;">For distributed shuffle operations like&nbsp;<code style="margin: 0px; padding: 0px;">reduceByKey</code>&nbsp;and&nbsp;<code style="margin: 0px; padding: 0px;">join</code>, the largest number of partitions in a parent RDD. For operations like<code style="margin: 0px; padding: 0px;">parallelize</code>&nbsp;with no parent RDDs, it depends on the cluster manager:
             <ul style="margin: 0px 0px 0px 30px; padding: 0px; word-break: break-all;">
                 <li style="margin: 0px 0px 1em; padding: 0px; list-style: disc;">Local mode: number of cores on the local machine</li>
                 <li style="margin: 0px 0px 1em; padding: 0px; list-style: disc;">Mesos fine grained mode: 8</li>
                 <li style="margin: 0px 0px 1em; padding: 0px; list-style: disc;">Others: total number of cores on all executor nodes or 2, whichever is larger</li>
             </ul>
             </td>
             <td style="margin: 0px; padding: 3px; border-style: solid; border-color: silver; border-collapse: collapse;">Default number of partitions in RDDs returned by transformations like&nbsp;<code style="margin: 0px; padding: 0px;">join</code>,&nbsp;<code style="margin: 0px; padding: 0px;">reduceByKey</code>, and&nbsp;<code style="margin: 0px; padding: 0px;">parallelize</code>&nbsp;when not set by user.</td>
         </tr>
     </tbody>
</table>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">from:<a href="http://spark.apache.org/docs/latest/tuning.html" target="_blank" style="margin: 0px; padding: 0px; color: #000000;">http://spark.apache.org/docs/latest/tuning.html</a></p>
<h2>Level of Parallelism</h2>
<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; line-height: 21.6px; background-color: #ffffff;">Clusters will not be fully utilized unless you set the level of parallelism for each operation high enough. Spark automatically sets the number of &#8220;map&#8221; tasks to run on each file according to its size (though you can control it through optional parameters to&nbsp;<code style="margin: 0px; padding: 0px;">SparkContext.textFile</code>, etc), and for distributed &#8220;reduce&#8221; operations, such as&nbsp;<code style="margin: 0px; padding: 0px;">groupByKey</code>&nbsp;and&nbsp;<code style="margin: 0px; padding: 0px;">reduceByKey</code>, it uses the largest parent RDD&#8217;s number of partitions. You can pass the level of parallelism as a second argument (see the&nbsp;<a href="http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.rdd.PairRDDFunctions" style="margin: 0px; padding: 0px; color: #000000;"><code style="margin: 0px; padding: 0px;">spark.PairRDDFunctions</code></a>&nbsp;documentation), or set the config property<code style="margin: 0px; padding: 0px;">spark.default.parallelism</code>&nbsp;to change the default. In general,&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffff00;">we recommend 2-3 tasks per CPU core in your cluster.<br />
</span>
<br />
<br />
原文地址：<span style="font-family: verdana, &quot;courier new&quot;; font-size: 14px; line-height: 21px;">http://www.cnblogs.com/wrencai/p/4231966.html</span></p><img src ="http://www.blogjava.net/cnfree/aggbug/431773.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2016-09-08 13:07 <a href="http://www.blogjava.net/cnfree/archive/2016/09/08/431773.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java反编译工具 Eclipse Class Decompiler 2.10 已发布，支持多种反编译器</title><link>http://www.blogjava.net/cnfree/archive/2016/05/13/430485.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Fri, 13 May 2016 06:23:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2016/05/13/430485.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/430485.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2016/05/13/430485.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/430485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/430485.html</trackback:ping><description><![CDATA[Eclipse Class Decompiler是一款Eclipse插件，<strong>整合了多种反编译器，和Eclipse Class Viewer无缝集成，能够很方便的使用插件查看类库源码，进行Debug调试。<br />同时还提供了在线自动查找源代码，查看Class二进制字节码的功能。</strong>&nbsp;<br /><br />Eclipse Class Decompiler对JDK的最低要求为JDK1.6, 能反编译和debug各版本的Class文件，支持JDK8的Lambda语法，同时支持中文等非Ascii码字符集的解析，支持Eclipse 3.6及以上所有版本的Eclipse。<br /><br /><strong style="color: #ff0000;">本插件支持Windows，Linux，Macosx 32位及64位操作系统。</strong><strong><br /></strong><br />Github项目地址为：<a href="https://github.com/cnfree/Eclipse-Class-Decompiler">https://github.com/cnfree/Eclipse-Class-Decompiler</a><br /><br />请通过以下地址选择一个可用的源在线安装：<br /><br /><span style="color: #333333; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; line-height: 20px; background-color: #ffffff;"><a href="http://cnfree.github.io/Eclipse-Class-Decompiler/update"></a><a href="http://cnfree.github.io/Eclipse-Class-Decompiler/update"><strong>http://cnfree.github.io/Eclipse-Class-Decompiler/update<br /></strong></a></span><span style="color: #333333; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; line-height: 20px; background-color: #ffffff;"><a href="http://raw.githubusercontent.com/cnfree/eclipse/master/decompiler/update"><strong>http://raw.githubusercontent.com/cnfree/eclipse/master/decompiler/update/</strong><br /></a></span><span style="color: #333333; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; line-height: 20px; background-color: #ffffff;"><a href="http://www.cpupk.com/decompiler/update/"><strong>http://www.cpupk.com/decompiler/update/<br /><br /></strong></a></span>离线包下载地址：<br /><div><span style="color: #333333; font-family: &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; line-height: 20px; background-color: #ffffff;"><a href="https://github.com/cnfree/Eclipse-Class-Decompiler/releases/download/v2.10.0/eclipse-class-decompiler-update_v2.10.0.zip"><strong>https://github.com/cnfree/Eclipse-Class-Decompiler/releases/download/v2.10.0/eclipse-class-decompiler-update_v2.10.0.zip<br /><br /></strong></a></span></div>&nbsp;<br /><strong>插件使用说明：<br /></strong><br />下图为Eclipse Class Decompiler的首选项页面，可以选择缺省的反编译器工具，并进行反编译器的基本设置。缺省的反编译工具为JD-Core，JD-Core更为先进一些，支持泛型、Enum、注解等JDK1.5以后才有的新语法。<br /><br /><div></div>首选项配置选项：<br />1.重用缓存代码：只会反编译一次，以后每次打开该类文件，都显示的是缓存的反编译代码。<br />2.忽略已存在的源代码：若未选中，则查看Class文件是否已绑定了Java源代码，如果已绑定，则显示Java源代码，如果未绑定，则反编译Class文件。若选中此项，则忽略已绑定的Java源代码，显示反编译结果。<br />3.显示反编译器报告：显示反编译器反编译后生成的数据报告及异常信息。<br />4.使用Eclipse代码格式化工具：使用Eclipse格式化工具对反编译结果重新格式化排版，反编译整个Jar包时，此操作会消耗一些时间。<br />5.使用Eclipse成员排序：使用Eclipse成员排序对反编译结果重新格式化排版，反编译整个Jar包时，此操作会消耗大量时间。<br />6.以注释方式输出原始行号信息：如果Class文件包含原始行号信息，则会将行号信息以注释的方式打印到反编译结果中。<br />7.根据行号对齐源代码以便于调试：若选中该项，插件会采用AST工具分析反编译结果，并根据行号信息调整代码顺序，以便于Debug过程中的单步跟踪调试。<br />8.设置类反编译查看器作为缺省的类文件编辑器：默认为选中，将忽略Eclipse自带的Class Viewer，每次Eclipse启动后，默认使用本插件提供的类查看器打开Class文件。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/cnfree/Preference.png" width="775" height="514" alt="" /><br /><br />插件提供了系统菜单，工具栏，当打开了插件提供的类反编译查看器后，会激活菜单和工具栏选项，可以方便的进行首选项配置，切换反编译工具重新反编译，以及导出反编译结果。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/cnfree/Menu.png" width="479" height="157" alt="" /><br /><br /><img src="http://www.blogjava.net/images/blogjava_net/cnfree/Toolbar.png" width="408" height="211" alt="" /><br /><br /><br /><div>类反编译查看器右键菜单包含了Eclipse自带类查看器右键菜单的全部选项，并增加了一个&#8220;导出反编译源代码&#8221;菜单项。</div><img src="http://www.blogjava.net/images/blogjava_net/cnfree/export.png" width="547" height="286" alt="" /><br /><br /><br />打开项目路径下的Class文件，如果设置类反编译查看器为缺省的查看器，直接双击Class文件即可，如果没有设置为缺省查看器，可以使用右键菜单进行查看。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/cnfree/Context.png" alt="" /><br /><br /><br />同时插件也支持直接将外部的Class文件拖拽到Eclipse编辑器中进行反编译。<br /><br /><br />Eclipse Class Decompiler插件也提供了反编译整个Jar文件或者Java包的反编译。该操作支持Package Explorer对包显示布局的操作，如果是平铺模式布局，则导出的源代码不包含子包，如果是层级模式布局，则导出选中的包及其所有的子包。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/cnfree/ExportPackage.png" width="486" height="171" alt="" /><br /><br /><br /><div>Debug调试：可以在首选项选中对齐行号进行单步跟踪调试，和普通的包含源代码时的调试操作完全一致，同样的也可以设置断点进行跟踪。当透视图为Debug时，插件自动生成行号并进行对齐方便调试代码，无需进行任何设置。</div><img src="http://www.blogjava.net/images/blogjava_net/cnfree/Debug.png" alt="" /><br /><br />博文地址：<a href="http://www.blogjava.net/cnfree/archive/2012/10/30/390457.html">http://www.blogjava.net/cnfree/archive/2012/10/30/390457.html</a><img src ="http://www.blogjava.net/cnfree/aggbug/430485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2016-05-13 14:23 <a href="http://www.blogjava.net/cnfree/archive/2016/05/13/430485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java应用定制工厂使用手册（一）</title><link>http://www.blogjava.net/cnfree/archive/2013/03/03/395999.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Sun, 03 Mar 2013 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2013/03/03/395999.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/395999.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2013/03/03/395999.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/395999.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/395999.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 16px; background-color: #ffffff;">Java应用定制工厂（以下简称为JCB，Java Customization Builder）是一个针对Java轻量级桌面应用进行精简优化的小工具，使用它可以精简你的jar包，并自动生成一个精简的JRE，也可以使用它生成一个Exe启动引导程序，并且能够对你的Java应用自动做Pack200和Unpack200处理。使用本工具定制的Java桌面应用通常不会超过10M（包含JRE），SWT客户端程序相对于Swing客户端程序更小，一般不会超过5M。<br />
<br />
</span>JCB是一个Java应用，所以目标机器上必须安装1.5以上版本的JDK用以启动JCB，但是JCB可以用来精简1.4版的JRE，并且JRE1.4精简后的体积远小于1.5以上的版本。<br />
<br />
1.新建JCB项目<br />
精简JRE的步骤比较繁琐，有可能精简失败，为了不重复之前的步骤，JCB提供一个项目文件用来保存精简配置信息，扩展名为jcprj。这里我们创建一个项目，名为JCB<br />
<br />
<div style="text-align: left;"><img src="http://www.blogjava.net/images/blogjava_net/cnfree/create_jcb.png" width="516" height="341" alt="" /></div>
<br />
Wizard需要输入一个工程名和指定工程位置，至于下面的应用程序位置和定制JRE位置由JCB自动指定，这儿显示出来仅供参考。<br />
<br />
<span style="color: #ff0000;">此时最好Ctrl+S保存一下项目，否则退出后你之前的配置信息会全部丢失，因为你并没有制定一个可用的项目配置文件。</span><br />
<br />
2. 配置JCB项目<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jcb_setting.png" width="850" height="615" alt="" /><br />
<br />
首先指定项目需要的jar文件，然后依次选择项目的main class，启动路径默认为空，一般来说无需指定。然后设定应用程序参数和虚拟机参数。最后选定需要精简的JRE，JCB当前支持1.4-1.7版本的JRE，未来可能会支持更高版本的JRE。<br />
<br />
右下角有2个单选按钮：全部重新运行和增量运行。全部重新运行就会放弃之前的运行结果，增量运行就是会保留以前的运行结果。<br />
<br />
然后点击&#8220;以Verbose模式运行&#8221;按钮。Verbose模式运行Java程序，会显示JVM加载的全部类信息，JCB需要这些类信息进行JRE的精简，所以请尽可能的把应用所有的功能尽可能的跑一遍，跑的越全面，导致精简出错的可能性就越低。<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jcb_verbose.png" width="850" height="615" alt="" /><br />
<br />
Verbose运行结果，这个页面的显示信息仅供参考，无实际用处。<br />
<br />
3. 分析项目的类依赖项<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jcb_analyze.png" width="850" height="615" alt="" /><br />
<br />
分析类依赖模式有2个选项：重新完全分析和增量分析。完全分析会花费较多的时间。当使用verbose模式增量运行后，可以使用增量模式分析类依赖项，这样可以节约大量的时间。类依赖分析会反编译所有运行的类，分析类引用关系，但是无法获取Class.forName这类动态类加载信息，所以需要Verbose模式运行的尽量全面，以避免这些动态加载的类的缺失。<br />
<br />
为什么需要分析类依赖关系呢？因为不同的操作系统，不同的硬件配置，JRE可能会采取策略模式加载不同的类，或者一些异常，Verbose模式一般不会加载，这样换个硬件环境，仅仅使用Verbose模式的类可能会导致ClassNotFound这样的异常，导致Java程序崩溃。<br />
<br />
<br />
4. 精简JRE<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jcb_slim.png" width="850" height="615" alt="" /><br />
<br />
精简JRE有两种模式：使用Verbose运行结果和使用类依赖分析结果。前者只包含Verbose分析出来的类，精简出来的JRE包很小，但是基本不具备跨平台性。所以一般来说推荐选择后者。<br />
<br />
如果你的程序包含Swing的客户端，并且比较复杂的话，最好选中包含Swing选项。因为Swing的设计完全是动态化的加载，全部使用Class.forName方式，类依赖分析对Swing是无效的。当然选中该选项后，JRE的体积会增加许多。比较好的解决方案，是使用SWT替代Swing进行开发，或者尽量把你的程序跑全面，包括各种异常界面都跑出来。<br />
<br />
右下角有两个按钮，是用来自定义类和资源文件的，比如移除JAR包的MD5文件或者无用的文件。或者测试运行发现ClassNotFound异常，手动把缺少的类加进去，然后JCB会自动运行增量类依赖分析加载所有可能需要的类。<br />
<br />
选择左上角的&#8220;精简Jar包&#8221;按钮，就可以对JRE进行精简了，精简完毕后可以点击&#8220;查看精简结果&#8221;按钮进行查看。<br />
<br />
5.定制JRE<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jre_slim.png" width="850" height="615" alt="" /><br />
<br />
上图显示了JRE精简结果，JCB会自动分析所有的Class，生成精简版JRE，包括需要的JAR，DLL和资源文件。一般来说精简出来的JRE，普通功能都能正确完成，但是不排除有些功能不能正常使用，比如缺少某个资源文件或者DLL，需要手工添加。<br />
<br />
为了保证精简的正确性，你需要进行运行测试，这一步是必须的，而且最好和Verbose运行模式一样，把所有的功能都跑一遍，确认精简无误。<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/cnfree/jre_test.png" border="0" alt="" width="850" height="615" /><br />
<br />
如果测试运行有误的话，请根据运行错误报告进行分析，如果缺少类，请使用Verbose模式重新运行相应的功能，或者在步骤四手工添加需要的类，然后重新生成依赖的JRE。如果缺少相关的DLL或者资源文件，也请手工添加，并且取消步骤四的&#8220;清理工作区选项&#8221;，否则每次精简JRE都需要重新手工添加。<br />
<br />
<span style="color: #ff0000;">到此为止，精简JRE部分就算全部完成了，你最好使用Ctrl+S保存一下结果，以避免下次重做项目。</span><br /><br /><strong>JCB项目下载地址：<a href="http://www.sourceforge.net/projects/jcb">http://www.sourceforge.net/projects/jcb</a></strong><img src ="http://www.blogjava.net/cnfree/aggbug/395999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2013-03-03 17:25 <a href="http://www.blogjava.net/cnfree/archive/2013/03/03/395999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编程珠玑第二章</title><link>http://www.blogjava.net/cnfree/archive/2012/11/24/391908.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Sat, 24 Nov 2012 14:21:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2012/11/24/391908.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/391908.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2012/11/24/391908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/391908.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/391908.html</trackback:ping><description><![CDATA[1. 40亿个无符号整数，找出一个不在这40亿个整数中的数。可以换个方向思考， 99个小于100的数，找出一个不在这99个数中的小于100的数。<br />首先把这99个数分为10组，按高位为0-9分，然后计算每组的数量，数量最少的那个肯定就是缺失的那个，然后递归&#8230;&#8230;找最少的那个，组合起来的数肯定是缺失的。答案是按位运算找，和这个类似。<br /><br />2. 43亿个无符号整数，找出一个重复的整数。也就是101个小于100的数，找出重复的那个数来。<br />首先把这99个数分为10组，按高位为0-9分，然后计算每组的数量，数量最多的那组，肯定有重复的，一次类推找第二位&#8230;&#8230;<img src ="http://www.blogjava.net/cnfree/aggbug/391908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2012-11-24 22:21 <a href="http://www.blogjava.net/cnfree/archive/2012/11/24/391908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The difference between dependency and association</title><link>http://www.blogjava.net/cnfree/archive/2012/11/19/391572.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Mon, 19 Nov 2012 05:16:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2012/11/19/391572.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/391572.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2012/11/19/391572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/391572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/391572.html</trackback:ping><description><![CDATA[When a object creates a new object, please use the dependency.<br /><br />When a object just uses a object, please use the association.&nbsp;<img src ="http://www.blogjava.net/cnfree/aggbug/391572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2012-11-19 13:16 <a href="http://www.blogjava.net/cnfree/archive/2012/11/19/391572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>研磨设计模式……  </title><link>http://www.blogjava.net/cnfree/archive/2012/11/14/391282.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Tue, 13 Nov 2012 16:22:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2012/11/14/391282.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/391282.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2012/11/14/391282.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/391282.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/391282.html</trackback:ping><description><![CDATA[<span style="color: #222222; font-family: arial, sans-serif; line-height: 20px; font-size: small; "><h3><nobr>comparator</nobr>&nbsp;</h3></span><div>Decorator Pattern and Adapter Pattern have the same alias name: wrapper. But they face different aspects. Decorator pattern changes the object function, but the adapter pattern changes the interface.<br /><br />The typical decorator pattern is the java OutputStream, you can use the BufferedOutputStream to wrap it, then get the extra function.<br />The typical adapter pattern in the BIRT is the ElementAdapter, it can convert any object to an other object.<br /><br /><div>Decorator pattern must extend the class which you want to wrap, but the adapter class must implements the interface using by the client.</div><font class="Apple-style-span" face="宋体"><span class="Apple-style-span" style="line-height: 24px; "><br /><br />FlyWeight pattern extracts the same part of some different objects, and the part doesn't be changed when these objects changed. String class uses the FlyWeight pattern, jface&nbsp;</span></font>ImageRegistry also uses it.&nbsp;<br /><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; ">FlyWeight&nbsp;can have a interface to get external data, and change the external data's status, but&nbsp;<span class="Apple-style-span" style="font-family: verdana, 'courier new'; line-height: 21px; ">FlyWeight internal status shouldn't be changed.<br /><br /></span>The Collections.sort() method implementation contains template method design pattern and strategy design pattern, but it doesn't contain the visitor design pattern.&nbsp;The Collections.sort() method uses the merge sort algorithm, you can't change it, but you can change the comparator logic, it's one step of the sort algorithm. So it's a template method pattern, but not a classic implementation, it uses the callback method to implement the pattern, but not extending the parent template class. The comparator class use the strategy design pattern, it not a visitor pattern, visitor pattern have a accept method to operate the element to deal some logic.&nbsp;</span><span class="Apple-style-span" style="color: #222222; font-family: arial, sans-serif; line-height: 20px; background-color: #ffffff; font-size: small; "><h3 class="r" style="font-size: medium; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; display: block; line-height: 1; overflow-x: hidden; overflow-y: hidden; text-overflow: ellipsis; white-space: nowrap; "><br /></h3></span><br /></div><img src ="http://www.blogjava.net/cnfree/aggbug/391282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2012-11-14 00:22 <a href="http://www.blogjava.net/cnfree/archive/2012/11/14/391282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>排序1+4：归并排序（MergeSort）和堆排序（HeapSort）（转）</title><link>http://www.blogjava.net/cnfree/archive/2012/11/10/391154.html</link><dc:creator>三人行，必有我师焉</dc:creator><author>三人行，必有我师焉</author><pubDate>Sat, 10 Nov 2012 15:18:00 GMT</pubDate><guid>http://www.blogjava.net/cnfree/archive/2012/11/10/391154.html</guid><wfw:comment>http://www.blogjava.net/cnfree/comments/391154.html</wfw:comment><comments>http://www.blogjava.net/cnfree/archive/2012/11/10/391154.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/cnfree/comments/commentRss/391154.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cnfree/services/trackbacks/391154.html</trackback:ping><description><![CDATA[<p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><span style="line-height: 28px; font-size: 14pt;"><strong>1 归并排序（MergeSort）</strong></span><br /><br />归并排序最差运行时间是O(nlogn)，它是利用递归设计程序的典型例子。<br /><br />归并排序的最基础的操作就是合并两个已经排好序的序列。<br /><br />假设我们有一个没有排好序的序列，那么首先我们使用分割的办法将这个序列分割成一个一个已经排好序的子序列。然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。<br /><br /><img alt="" src="http://images.cnblogs.com/cnblogs_com/flyingbread/MergeSort.jpg" width="561" border="0" height="549" style="border: 0px;" /><br /><br />从上图可以看出，我们首先把一个未排序的序列从中间分割成2部分，再把2部分分成4部分，依次分割下去，直到分割成一个一个的数据，再把这些数据两两归并到一起，使之有序，不停的归并，最后成为一个排好序的序列。<br /><br />如何把两个已经排序好的子序列归并成一个排好序的序列呢？可以参看下面的方法。<br /><br />假设我们有两个已经排序好的子序列。<br />序列A：1 23 34 65<br />序列B：2 13 14 87<br />那么可以按照下面的步骤将它们归并到一个序列中。<br /><br />（1）首先设定一个新的数列C[8]。<br />（2）A[0]和B[0]比较，A[0] = 1，B[0] = 2，A[0] &lt; B[0]，那么C[0] = 1<br />（3）A[1]和B[0]比较，A[1] = 23，B[0] = 2，A[1]&nbsp;&gt; B[0]，那么C[1] = 2<br />（4）A[1]和B[1]比较，A[1] = 23，B[1] = 13，A[1]&nbsp;&gt; B[1]，那么C[2] = 13<br />（5）A[1]和B[2]比较，A[1] = 23，B[2] = 14，A[1]&nbsp;&gt; B[2]，那么C[3] = 14<br />（6）A[1]和B[3]比较，A[1] = 23，B[3] = 87，A[1] &lt; B[3]，那么C[4] = 23<br />（7）A[2]和B[3]比较，A[2] = 34，B[3] = 87，A[2] &lt; B[3]，那么C[5] = 34<br />（8）A[3]和B[3]比较，A[3] = 65，B[3] = 87，A[3] &lt; B[3]，那么C[6] = 65<br />（9）最后将B[3]复制到C中，那么C[7] = 87。归并完成。<br /><br />如果我们清楚了上面的分割和归并过程，那么我们就可以用递归的方法得到归并算法的实现。</p><div style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 1006.453125px; background-color: #eeeeee;"><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MergeSorter<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;myArray;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;arraySize;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Sort(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;a&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myArray&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arraySize&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray.Length;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MergeSort();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span>&nbsp;<span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;利用归并的方法排序数组，首先将序列分割<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;然后将数列归并，这个算法需要双倍的存储空间<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;时间是O(nlgn)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span>&nbsp;<span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #808080;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;MergeSort()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;temp&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">new</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">[arraySize];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MSort(&nbsp;temp,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;arraySize&nbsp;</span><span style="color: #000000;">-</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;MSort(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;temp,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;left,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;right)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;mid;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(right&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;left)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(right&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;left)&nbsp;</span><span style="color: #000000;">/</span>&nbsp;<span style="color: #000000;">2</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MSort(&nbsp;temp,&nbsp;left,&nbsp;mid);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">分割左边的序列</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MSort(temp,&nbsp;mid</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;right);</span><span style="color: #008000;">//</span><span style="color: #008000;">分割右边的序列</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Merge(temp,&nbsp;left,&nbsp;mid</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;right);</span><span style="color: #008000;">//</span><span style="color: #008000;">归并序列</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Merge(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;temp,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;left,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;mid,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;right)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;left_end,&nbsp;num_elements,&nbsp;tmp_pos;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left_end&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">-</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;left;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_elements&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;right&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;left&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;((left&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;left_end)&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;(mid&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;right))&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(myArray[left]&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;myArray[mid])&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将左端序列归并到temp数组中</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[tmp_pos]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[left];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;left&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">//</span><span style="color: #008000;">将右端序列归并到temp数组中</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[tmp_pos]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[mid];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(left&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;left_end)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">拷贝左边剩余的数据到temp数组中</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[tmp_pos]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[left];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;left&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(mid&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;right)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">拷贝右边剩余的数据到temp数组中</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[tmp_pos]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[mid];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;mid&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tmp_pos&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;num_elements;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将所有元素拷贝到原始数组中</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myArray[right]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;temp[right];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;right&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;right&nbsp;</span><span style="color: #000000;">-</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><br />归并排序算法是一种O(nlogn)的算法。它的最差，平均，最好时间都是O(nlogn)。但是它需要额外的存储空间，这在某些内存紧张的机器上会受到限制。<br /><br />归并算法是又分割和归并两部分组成的。对于分割部分，如果我们使用二分查找的话，时间是O(logn)，在最后归并的时候，时间是O(n)，所以总的时间是O(nlogn)。<br /><br /><span style="line-height: 28px; font-size: 14pt;"><strong>2 堆排序（HeapSort）</strong></span><br /><br />堆排序属于百万俱乐部的成员。它特别适合超大数据量（百万条记录以上）的排序。因为它并不使用递归（因为超大数据量的递归可能会导致堆栈溢出），而且它的时间也是O(nlogn)。还有它并不需要大量的额外存储空间。<br /><br />堆排序的思路是:<br /><br />(1)将原始未排序的数据建成一个堆。<br />(2)建成堆以后，最大值在堆顶，也就是第0个元素，这时候将第零个元素和最后一个元素交换。<br />(3)这时候将从0到倒数第二个元素的所有数据当成一个新的序列，建一个新的堆，再次交换第一个和最后一个元素，依次类推，就可以将所有元素排序完毕。<br /><br />建立堆的过程如下面的图所示:<br /><img alt="" src="http://images.cnblogs.com/cnblogs_com/flyingbread/BuildHeap.JPG" width="754" border="0" height="402" style="border: 0px;" /><br /><br />堆排序的具体算法如下：</p><div style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 1006.453125px; background-color: #eeeeee;"><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;HeapSorter&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;myArray;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;arraySize;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Sort(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;a&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myArray&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;a;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arraySize&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray.Length;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HeapSort();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;HeapSort()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuildHeap();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将原始序列建成一个堆</span><span style="color: #008000;"><br /></span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;arraySize&nbsp;</span><span style="color: #000000;">&gt;</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arraySize</span><span style="color: #000000;">--</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exchange&nbsp;(&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;arraySize&nbsp;);</span><span style="color: #008000;">//</span><span style="color: #008000;">将最大值放在数组的最后</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DownHeap&nbsp;(&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;);&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将序列从0到n-1看成一个新的序列，重新建立堆</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;BuildHeap()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;v</span><span style="color: #000000;">=</span><span style="color: #000000;">arraySize</span><span style="color: #000000;">/</span><span style="color: #000000;">2</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;v</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;v</span><span style="color: #000000;">--</span><span style="color: #000000;">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DownHeap&nbsp;(&nbsp;v&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">利用向下遍历子节点建立堆</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;DownHeap(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;v&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;w&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">2</span>&nbsp;<span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;v&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;节点w是节点v的第一个子节点</span><span style="color: #008000;"><br /></span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(w&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;arraySize)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;w</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span>&nbsp;<span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;arraySize&nbsp;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;如果节点v下面有第二个字节点</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;myArray[w</span><span style="color: #000000;">+</span><span style="color: #000000;">1</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;myArray[w]&nbsp;)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w</span><span style="color: #000000;">++</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;将子节点w设置成节点v下面值最大的子节点<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;节点v已经大于子节点w，有了堆的性质，那么返回</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;myArray[v]&nbsp;</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">&nbsp;myArray[w]&nbsp;)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exchange(&nbsp;v,&nbsp;w&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;如果不是，就交换节点v和节点w的值</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;w;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #000000;">2</span>&nbsp;<span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;v&nbsp;</span><span style="color: #000000;">+</span>&nbsp;<span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;继续向下找子节点</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">交换数据</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Exchange(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;t&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myArray[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myArray[j];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myArray[j]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;t;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /></span></div><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><br />&nbsp;</p><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">堆排序主要用于超大规模的数据的排序。因为它不需要额外的存储空间，也不需要大量的递归。</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">3 几种O(nlogn)算法的初步比较</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">我们可以从下表看到几种O(nlogn)算法的效率的区别。所有的数据都使用.Net的Random类产生，每种算法运行100次，时间的单位为毫秒。</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><table border="1" cellpadding="3" cellspacing="0" style="border-style: solid; border-color: #c0c0c0; border-collapse: collapse; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><tbody><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;"><br /></td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">500随机整数</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">5000随机整数</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">20000随机整数</td></tr><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">合并排序</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">0.3125</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">1.5625</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">7.03125</td></tr><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">&nbsp;Shell排序</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">0.3125</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">1.25</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">6.875</td></tr><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">堆排序</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">0.46875</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">2.1875</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">6.71875</td></tr><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">快速排序</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">0.15625</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">0.625</td><td style="font-size: 12px; color: #454545; border-style: solid; border-color: #c0c0c0; border-collapse: collapse; padding: 3px; word-break: normal !important;">2.8125</td></tr></tbody></table><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">从上表可以明显地看出，快速排序是最快的算法。这也就给了我们一个结论，对于一般的应用来说，我们总是选择快速排序作为我们的排序算法，当数据量非常大（百万数量级）我们可以使用堆排序，如果内存空间非常紧张，我们可以使用Shell排序。但是这意味着我们不得不损失速度。&nbsp;</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">/******************************************************************************************</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*【Author】：flyingbread</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*【Date】：2007年2月2日</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*【Notice】：</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*1、本文为原创技术文章，首发博客园个人站点(</span><a href="http://flyingbread.cnblogs.com/" style="color: #1a8bc8; text-decoration: initial; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">http://flyingbread.cnblogs.com/</a><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">)，转载和引用请注明作者及出处。</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*2、本文必须全文转载和引用，任何组织和个人未授权不能修改任何内容，并且未授权不可用于商业。</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;*3、本声明为文章一部分，转载和引用必须包括在原文中。</span><br style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;******************************************************************************************/</span><img src ="http://www.blogjava.net/cnfree/aggbug/391154.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cnfree/" target="_blank">三人行，必有我师焉</a> 2012-11-10 23:18 <a href="http://www.blogjava.net/cnfree/archive/2012/11/10/391154.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>