首页 文章 精选 留言 我的

精选列表

搜索[云数据库 Redis®],共10034篇文章
优秀的个人博客,低调大师

【Windows10 IoT开发系列】API 移植工具

原文: 【Windows10IoT开发系列】API移植工具 Windows 10 IoT Core 中是否提供你的当前 Win32 应用程序或库所依赖的 API? 如果不提供,是否存在可使用的等效 API? 此工具可以为你回答这些问题,并协助你将你的当前 Win32 应用程序和库迁移到 Windows IoT Core。 Windows 10 IoT 核心版 API 移植工具可在ms-iot/iot-utilities github 存储库中找到。下载存储库zip并将 IoTAPIPortingTool 文件夹复制到本地计算机。在 Visual Studio 2015 中打开IoTAPIPortingTool.sln并生成项目。这将生成IotAPIPortingTool.exe。 可通过运行IoTAPIPortingTool.exe [-os]使用该工具。 应提供你的 exe 和/或 dll 文件所在的目录的路径。 如果你不计划使用 UWP,应指定 -os 。默认情况下,该工具针对 WindowsUWP 平台验证你的二进制文件。 Note:IoTAPIPortingTool.exe must be run from a Visual Studio​Developer Command Prompt. 该工具将生成名为IoTAPIPortingTool.csv (如果已指定操作系统则为IoTAPIPortingToolOS.csv)的逗号分隔的值 (csv) 文件,并且摘要将在命令行上。在 Excel 中打开 .csv文件来分析完整输出。 声明:本文主要资料来源为Windows 开发人员中心。

优秀的个人博客,低调大师

Manifest.xml 入门基础 (三) <uses-sdk>标签

Manifest.xml 入门基础 (三) <uses-sdk>标签 <uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="integer" android:maxSdkVersion="integer" /> 用于表明应用程序与一个或多个版本 Android 平台的兼容性,以整数型的 API 级别来表示。 应用程序声明的 API 级别将与给定的 Android 系统进行比较,不同 Android 设备的 API Level 可能各不相同。 不要去理会名称(指 uses-sdk),本元素是用于指定 API 级别 的,而不是指 SDK (软件开发包)或 Android 平台的版本号。 API 级别总是以一个整数值来表示。 API 级别是无法从相应的 Android 版本号推导出来的(比如,它既不是主版本号,也不是主版本号加小版本号)。 1.android:minSdkVersion 整数值,指定运行应用程序所需的最低 API 级别。 如果系统 API 级别低于本属性设定的值, Android 系统将阻止用户安装此应用程序。 本属性必需指定。 提醒: 如果未声明本属性,系统假定缺省值为“1”,这表示应用程序与所有版本的 Android 兼容。 如果应用程序无法兼容所有版本(比如,用到了 API 级别 3 才开始引入的 API ), 也没有声明正确的 android:minSdkVersion, 那么安装在低于 API 级别 3 的系统中后,一旦在运行过程中试图访问不可用的 API,应用程序就会崩溃。 因此,请确保在 minSdkVersion 属性中声明正确的 API 级别。 2.android:targetSdkVersion 整数值,指定应用程序的目标 API 级别。如果不设置本属性,缺省值等于已给定的 minSdkVersion。 本属性将告知系统应用程序已经针对此目标版本进行了测试,系统不会启用任何与此目标版本相关的向前兼容特性。 应用程序仍然能够在较低版本(最低至 minSdkVersion)的系统上运行。 随着 Android 的版本更新,某些特性甚至组件外观都会发生变化。 不过,当平台的 API 级别高于应用程序声明的 targetSdkVersion时,系统会启用兼容性特性,应用程序仍然可以按预计方式运行。 通过把 targetSdkVersion 设定为所需的平台版本,你可以禁用兼容特性。 比如,将本值设置为大于等于“11”,当运行于 Android 3.0 以上版本时, 系统就能在应用程序上使用新加入的默认主题(Holo),并且在大屏幕设备上时还会禁用 屏幕兼容模式 (因为 API 级别 11 隐含了对大屏幕的支持)。 根据本属性设定的值,有系统可能会启用很多兼容性特性。 有相当多的特性在参考文档 Build.VERSION_CODES 中分版本进行了说明。 为了能随着 Android 版本的发布而对应用程序进行维护,你应该及时调大本属性值以匹配最新的 API 级别, 然后在对应版本的平台上对程序进行充分的测试。 3.android:maxSdkVersion 整数值,指定应用程序设计可运行的最高 API 级别。 为了说明本属性在系统更新后对应用程序的影响,请参阅以下例子: 某应用程序在 manifest 中声明了 maxSdkVersion=”5” ,并已在 Google Play 进行了发布。 有一个用户下载并安装了此应用程序,他的设备运行的是 Android 1.6 (API 级别 4)。 几星期后,用户通过无线系统把系统升级到了 Android 2.0(API 级别 5)。 升级完成后,系统会检查应用程序的 maxSdkVersion 并成功进行了重新校验,应用程序能够正常工作。 但是一段时间之后,设备又收到了另一个系统更新,这次是升级到 Android 2.0.1(API 级别 6)。 这次更新后系统无法再对应用程序进行重新校验了,因为当前系统的 API 级别 (6)已经高于应用程序支持的最大版本(5)了。 系统会阻止用户使用此应用程序,实际上将会从设备上删除它。 警告: 不建议声明本属性。 首先,没有必要用本属性来阻止应用程序在新版本 Android 平台上的使用。 理论上讲,新版本的平台完全是向后全兼容的。 应用程序应该可以在新版本平台上正常运行,新版本不仅提供标准的API,还能开发最佳的体验。 其次请注意,在某些场合声明本属性,可能会 导致系统升级到高版本 API 后把应用程序删除。 大多数设备都会通过无线网络定期接收到系统更新,因此在设置本属性之前,你应该考虑对应用程序的影响。 什么是 API 级别 API 级别是一个整数值,它唯一标识了某版本 Android 平台所提供的 API 的版本。 Android 平台提供了一整套 API,应用程序可以用这些 API 与底层系统进行交互。 这套API由以下部分组成: 核心包和类 声明和访问资源时所用的 XML 格式的元素和属性 一些预设的 Intent 应用程序可请求的权限以及系统预设的权限 Android 平台每个较高版本都会包含之前的 API 更新。 API 的更新机制使得新版本的 API 可以与早期版本保持兼容。 也就是说,大部分的 API 改动都是新增功能,或是引入新 API ,或是替代原有功能。 作为 API 升级过程中的一部分工作,被替换的旧功能被视为过时功能但不会被删除。 因此,现有的应用程序仍然可以使用这些过时的功能。 在极少数情况下,一部分 API 可能会被修改或删除,通常这种改动只是为了确保 API 的稳定性及应用程序或系统的安全性。 早期版​​本的 API 剩余部分都将原封不动地带入新版本。 API 级别在 Android 中的用途 当用户尝试安装某应用程序时,或者在系统升级后对应用程序重新校验时, Android 系统首先会检查应用程序 manifest 中的 <uses-sdk> 属性, 并将其值与系统内部的 API 级别进行比较。 只有满足以下条件时,系统才会允许应用程序的安装: 如果声明了android:minSdkVersion属性,则其值必须小于等于当前系统的 API 级别值。 如果未声明,系统就会假定该应用程序运行需要的最低 API 级别是 1 。 如果声明了android:maxSdkVersion属性,则其值必须大于等于当前系统的 API 级别值。 如果未声明,系统就会假定该应用程序没有最高 API 级别的限制。

优秀的个人博客,低调大师

Apache Spark技术实战(二)KafkaWordCount &amp;PackratParsers实例 &amp;Spark Cassandra C...

<一>KafkaWordCount 概要 Spark应用开发实践性非常强,很多时候可能都会将时间花费在环境的搭建和运行上,如果有一个比较好的指导将会大大的缩短应用开发流程。Spark Streaming中涉及到和许多第三方程序的整合,源码中的例子如何真正跑起来,文档不是很多也不详细。 本篇主要讲述如何运行KafkaWordCount,这个需要涉及Kafka集群的搭建,还是说的越仔细越好。 搭建Kafka集群 步骤1:下载kafka 0.8.1及解压 wget https://www.apache.org/dyn/closer.cgi?path=/kafka/0.8.1.1/kafka_2.10-0.8.1.1.tgz tar zvxf kafka_2.10-0.8.1.1.tgz cd kafka_2.10-0.8.1.1 步骤2:启动zookeeper bin/zookeeper-server-start.sh config/zookeeper.properties 步骤3:修改配置文件config/server.properties,添加如下内容 host.name=localhost # Hostname the broker will advertise to producers and consumers. If not set, it uses the # value for "host.name" if configured. Otherwise, it will use the value returned from # java.net.InetAddress.getCanonicalHostName(). advertised.host.name=localhost 步骤4:启动Kafka server bin/kafka-server-start.sh config/server.properties 步骤5:创建topic bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 检验topic创建是否成功 bin/kafka-topics.sh --list --zookeeper localhost:2181 如果正常返回test 步骤6:打开producer,发送消息 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test ##启动成功后,输入以下内容测试 This is a message This is another message 步骤7:打开consumer,接收消息 bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test --from-beginning ###启动成功后,如果一切正常将会显示producer端输入的内容 This is a message This is another message 运行KafkaWordCount KafkaWordCount源文件位置 :examples/src/main/scala/org/apache/spark/examples/streaming/KafkaWordCount.scala 尽管里面有使用说明,见下文,但如果不是事先对Kafka有一定的了解的话,决然不知道这些参数是什么意思,也不知道该如何填写。 /** * Consumes messages from one or more topics in Kafka and does wordcount. * Usage: KafkaWordCount * is a list of one or more zookeeper servers that make quorum * is the name of kafka consumer group * is a list of one or more kafka topics to consume from * is the number of threads the kafka consumer should use * * Example: * `$ bin/run-example \ * org.apache.spark.examples.streaming.KafkaWordCount zoo01,zoo02,zoo03 \ * my-consumer-group topic1,topic2 1` */ object KafkaWordCount { def main(args: Array[String]) { if (args.length < 4) { System.err.println("Usage: KafkaWordCount ") System.exit(1) } StreamingExamples.setStreamingLogLevels() val Array(zkQuorum, group, topics, numThreads) = args val sparkConf = new SparkConf().setAppName("KafkaWordCount") val ssc = new StreamingContext(sparkConf, Seconds(2)) ssc.checkpoint("checkpoint") val topicpMap = topics.split(",").map((_,numThreads.toInt)).toMap val lines = KafkaUtils.createStream(ssc, zkQuorum, group, topicpMap).map(_._2) val words = lines.flatMap(_.split(" ")) val wordCounts = words.map(x => (x, 1L)) .reduceByKeyAndWindow(_ + _, _ - _, Minutes(10), Seconds(2), 2) wordCounts.print() ssc.start() ssc.awaitTermination() } } 讲清楚了写这篇博客的主要原因之后,来看一看该如何运行KafkaWordCount 步骤1:停止运行刚才的kafka-console-producer和kafka-console-consumer 步骤2:运行KafkaWordCountProducer bin/run-example org.apache.spark.examples.streaming.KafkaWordCountProducer localhost:9092 test 3 5 解释一下参数的意思,localhost:9092表示producer的地址和端口, test表示topic,3表示每秒发多少条消息,5表示每条消息中有几个单词 步骤3:运行KafkaWordCount bin/run-example org.apache.spark.examples.streaming.KafkaWordCount localhost:2181 test-consumer-group test 1 解释一下参数, localhost:2181表示zookeeper的监听地址,test-consumer-group表示consumer-group的名称,必须和$KAFKA_HOME/config/consumer.properties中的group.id的配置内容一致,test表示topic,1表示线程数。 <二>PackratParsers实例 概要 通过一个简明的Demo程序来说明如何使用scala中的PackratParsers DemoApp import scala.util.parsing.combinator.PackratParsers import scala.util.parsing.combinator.syntactical._ object Dotter extends StandardTokenParsers with PackratParsers { //定义分割符 lexical.delimiters ++= List(".",";","+","-","*") //合法的输入模式,支持加,减,乘 lazy val pgm : PackratParser[Int] = expr | minus|multiply //定义模式加 lazy val expr :PackratParser[Int]= num~"+"~num ^^ {case n1~"+"~n2 => n1.toInt + n2.toInt} //定义模式减 lazy val minus :PackratParser[Int]= num~"-"~num ^^ {case n1~"-"~n2 => n1.toInt - n2.toInt} lazy val multiply :PackratParser[Int]= num~"*"~num ^^ {case n1~"*"~n2 => n1.toInt * n2.toInt} lazy val num = numericLit def parse(input: String) = phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match { case Success(result, _) => println("Success!"); println(result);Some(result) case n @ _ => println(n);println("bla"); None } def main(args: Array[String]) { //定义list,::表示添加,Nil表示list结束 val prg = "12*2"::"24-4"::"3+5"::Nil prg.map(parse) } } parser中的表达式说明 A<~B 只保留左侧内容 A<~B 只保留A A~>B 只保留右侧内容 A~>B 只保留B ^^ 根据匹配结果生成语法短语 ^^^ 将语法短语转换成为另外的值,注意与^^的区别 ~ 连接符 A ̃B 表示模式匹配是B紧跟于A之后 | 或者 A|B 表示模式要么由A组成,要么由B组成 编译执行 将上述源码保存到文件dotter.scala。 编译 scalac dotter.scala 执行 scala -cp . Dotter <三>Spark Cassandra Connector的安装和使用 前提 假设当前已经安装好如下软件: jdk sbt git scala 安装cassandra 以archlinux为例,使用如下指令来安装Cassandra: yaourt -S cassandra 启动cassandra: cassandra -f 创建keyspace和table, 运行/usr/bin/cqlsh进入cql console,然后执行下述语句创建keyspace和table: CREATE KEYSPACE test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1 }; CREATE TABLE test.kv(key text PRIMARY KEY, value int); 添加记录,继续使用cql console: INSERT INTO test.kv(key, value) VALUES ('key1', 1); INSERT INTO test.kv(key, value) VALUES ('key2', 2); 验证记录已经插入成功,执行如下cql: select * from test.kv; 下载编译spark-cassandra-connector 下载最新的spark-cassandra-connector源码: git clone https://github.com/datastax/spark-cassandra-connector.git 编译: sbt package 这中间要等待比较长的时间,请保持足够的耐心。 运行spark-shell 首先请确保cassandra已经正常安装和运行,如有问题请返回开始的章节安装Cassandra。 如何添加相应的library来支持spark-cassandra-connector,并没有一个明确的文档说明,折腾了一个下午,终于弄出了一个最简的配置。 bin/spark-shell --driver-class-path /root/working/spark-cassandra-connector/spark-cassandra-connector/target/scala-2.10/spark-cassandra-connector_2.10-1.1.0-SNAPSHOT.jar: /root/.ivy2/cache/org.apache.cassandra/cassandra-thrift/jars/cassandra-thrift-2.0.9.jar: /root/.ivy2/cache/org.apache.thrift/libthrift/jars/libthrift-0.9.1.jar: /root/.ivy2/cache/org.apache.cassandra/cassandra-clientutil/jars/cassandra-clientutil-2.0.9.jar: /root/.ivy2/cache/com.datastax.cassandra/cassandra-driver-core/jars/cassandra-driver-core-2.0.4.jar: /root/.ivy2/cache/io.netty/netty/bundles/netty-3.9.0.Final.jar: /root/.ivy2/cache/com.codahale.metrics/metrics-core/bundles/metrics-core-3.0.2.jar: /root/.ivy2/cache/org.slf4j/slf4j-api/jars/slf4j-api-1.7.7.jar: /root/.ivy2/cache/org.apache.commons/commons-lang3/jars/commons-lang3-3.3.2.jar: /root/.ivy2/cache/org.joda/joda-convert/jars/joda-convert-1.2.jar: /root/.ivy2/cache/joda-time/joda-time/jars/joda-time-2.3.jar: /root/.ivy2/cache/org.apache.cassandra/cassandra-all/jars/cassandra-all-2.0.9.jar: /root/.ivy2/cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.7.2.jar 上述指令假设spark-cassandra-connector的源码是下载在$HOME/working目录下,请根据自己的情况作适当修改。 我是如何猜测到需要指定这些包依赖的呢?说白了,也很简单,就是执行以下指令,然后再查看相就的java进程中的运行参数。 #运行spark-cassandra-connector测试集 sbt test sbt it:test 当上述指令还在运行的时候,使用ps来查看java运行的参数,这样就反过来知道所需要的包依赖了。 ps -ef|grep -i java 测试程序 由于spark-shell会默认创建sc,所以首先需要停止掉默认的sc,然后利用新的配置来创建可以连接到cassandra的sc,示例代码如下: sc.stop import com.datastax.spark.connector._ import org.apache.spark._ val conf = new SparkConf() conf.set("spark.cassandra.connection.host", "127.0.0.1") val sc = new SparkContext("local[2]", "Cassandra Connector Test", conf) val table = sc.cassandraTable("test", "kv") table.count 如果一切正常会显示出如下结果: res3: Long = 2 小结 进入实战阶段,挑战会越来越多,保持足够的信心和耐心很重要。 本篇内容和实战一中的kafka cluster组织在一起的话,就会形成一个从前台到后台存储的完整处理链条。

优秀的个人博客,低调大师

从头学起android&amp;lt;android基本的绘图.四十六.&amp;gt;

在一般的图形渲染用户通常只需要重写onDraw()该方法可以是。但是假设,才能真正完成绘图操作。此外,我们需要掌握的四大核心经营类: android.graphics.Bitmap:主要表示的是一个图片的存储空间。所包括的图片能够来自于文件或由程序创建; android.graphics.Paint:基本的画图工具类,能够指定画图的样式; android.graphics.Canvas:是一个操作画图以及Bitmap的平台,相当于提供了一个画板的功能,在onDraw()方法的參数中也定义了此类型的參数,能够依靠此类完毕详细的画图操作。 android.graphics.drawable.Drawable:绘制图形的公共父类,能够绘制各种图形、图层等。 自己定义MyView组件 <span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.example.paintpic.MyView android:id="@+id/Myview" android:layout_width="wrap_content" android:layout_height="wrap_content" ></com.example.paintpic.MyView> </LinearLayout> </span> 主界面 <span style="font-size:18px;">package com.example.paintpic; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } </span> MyView设置 <span style="font-size:18px;">package com.example.paintpic; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; public class MyView extends View { public MyView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub // canvas是画板对象,背景是白色的 canvas.drawColor(Color.WHITE); // paint画笔工具 Paint paint = new Paint(); // 设置画笔颜色为蓝色 paint.setColor(Color.BLUE); // 为画板上画圆。圆心(50,50)半径50 canvas.drawCircle(50, 50, 50, paint); // 设置画笔颜色的颜色为红色 paint.setColor(Color.RED); // 画矩形 canvas.drawRect(100, 0, 160, 80, paint); // 画笔颜色为绿色 paint.setColor(Color.GREEN); // 画直线 canvas.drawLine(50, 110, 200, 110, paint); paint.setColor(Color.YELLOW); // Rect rect=new Rect(120, 120, 300, 300); // canvas.drawRect(rect, paint); // 使用RectF画多边形 RectF oval = new RectF(); oval.set(10.0f, 140.0f, 110.0f, 200.0f); canvas.drawOval(oval, paint); oval = new RectF(); oval.set(150.0f, 140.0f, 210.0f, 200.0f); canvas.drawArc(oval, 150.0f, 140.0f, true, paint); } } </span> 使用Canvas和point组件能够绘制出各种各样的图形,多用于游戏的开发。感兴趣的朋友能够自己了解下 根据第预测:bitmap图形组件 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4628322.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Spark的这些事&amp;lt;三&amp;gt;——spark常用的Transformations 和Actions

Transformations map,filter spark最长用的两个Transformations:map,filter,下面就来介绍一下这两个。 先看下面这张图: 从上图中可以清洗的看到 map和filter都是做的什么工作,那我们就代码演示一下。 val input = sc.parallelize(List(1,2,3,4)) val result1 = input.map(x=>x*x) val result2 = input.filter(x=>x!=1) print(result1.collect().mkString(",")) print("\n") print(result2.collect().mkString(",")) print("\n") 执行结果如下: 16/08/17 18:48:31 INFO DAGScheduler: ResultStage 0 (collect at Map.scala:17) finished in 0.093 s 16/08/17 18:48:31 INFO DAGScheduler: Job 0 finished: collect at Map.scala:17, took 0.268871 s 1,4,9,16 ........ 16/08/17 18:48:31 INFO DAGScheduler: ResultStage 1 (collect at Map.scala:19) finished in 0.000 s 16/08/17 18:48:31 INFO DAGScheduler: Job 1 finished: collect at Map.scala:19, took 0.018291 s 2,3,4 再回头看下上面那张图,是不是明白什么意思了! flatMap 另外一个常用的就是flatMap,输入一串字符,分割出每个字符 来用代码实践一下: val lines = sc.parallelize(List("hello world","hi")) val words = lines.flatMap (lines=>lines.split(" ")) print(words.first()) print("\n") 执行结果: 16/08/17 19:23:24 INFO DAGScheduler: Job 2 finished: first at Map.scala:24, took 0.016987 s hello 16/08/17 19:23:24 INFO SparkContext: Invoking stop() from shutdown hook 分隔符如果改一下的话: val words = lines.flatMap (lines=>lines.split(",")) 结果会怎样呢? 16/08/17 19:33:14 INFO TaskSchedulerImpl: Removed TaskSet 2.0, whose tasks have all completed, from pool hello world 16/08/17 19:33:14 INFO SparkContext: Invoking stop() from shutdown hook 和想象的一样吧~ distinct,distinct,intersection,subtract 还有几个比较常用的:distinct,distinct,intersection,subtract 来看看代码实践: val rdd1 = sc.parallelize(List("coffee","coffee","panda","monkey","tea")) val rdd2 = sc.parallelize(List("coffee","monkey","kitty")) rdd1.distinct().take(100).foreach(println) 结果: 16/08/17 19:52:29 INFO DAGScheduler: ResultStage 4 (take at Map.scala:30) finished in 0.047 s 16/08/17 19:52:29 INFO TaskSchedulerImpl: Removed TaskSet 4.0, whose tasks have all completed, from pool 16/08/17 19:52:29 INFO DAGScheduler: Job 3 finished: take at Map.scala:30, took 0.152405 s monkey coffee panda tea 16/08/17 19:52:29 INFO SparkContext: Starting job: take at Map.scala:32 代码: rdd1.union(rdd2).take(100).foreach(println) 结果: 6/08/17 19:52:29 INFO DAGScheduler: Job 5 finished: take at Map.scala:32, took 0.011825 s coffee coffee panda monkey tea coffee monkey kitty 16/08/17 19:52:30 INFO SparkContext: Starting job: take at Map.scala:34 16/08/17 19:52:30 INFO DAGScheduler: Registering RDD 11 (intersection at Map.scala:34) 16/08/17 19:52:30 INFO DAGScheduler: Registering RDD 12 (intersection at Map.scala:34) 代码: rdd1.intersection(rdd2).take(100).foreach(println) 结果: 16/08/17 19:52:30 INFO TaskSetManager: Finished task 0.0 in stage 9.0 (TID 9) in 31 ms on localhost (1/1) 16/08/17 19:52:30 INFO TaskSchedulerImpl: Removed TaskSet 9.0, whose tasks have all completed, from pool 16/08/17 19:52:30 INFO DAGScheduler: ResultStage 9 (take at Map.scala:34) finished in 0.031 s 16/08/17 19:52:30 INFO DAGScheduler: Job 6 finished: take at Map.scala:34, took 0.060785 s monkey coffee 16/08/17 19:52:30 INFO SparkContext: Starting job: take at Map.scala:36 代码: rdd1.subtract(rdd2).take(100).foreach(println) 结果: 16/08/17 19:52:30 INFO DAGScheduler: Job 6 finished: take at Map.scala:34, took 0.060785 s monkey coffee 16/08/17 19:52:30 INFO SparkContext: Starting job: take at Map.scala:36 再看看上面的图,很容易理解吧 Actions 常用的Transformations就介绍到这里,下面介绍下常用的Action: reduce,countByValue,takeOrdered,takeSample,aggregate 首先看一下:reduce val rdd5 = sc.parallelize(List(1,2,3,4)) print("reduce action:"+rdd5.reduce((x,y)=>x+y)+"\n") 16/08/18 11:51:16 INFO DAGScheduler: Job 15 finished: reduce at Function.scala:55, took 0.012698 s reduce action:10 16/08/18 11:51:16 INFO SparkContext: Starting job: aggregate at Function.scala:57 countByValue print(rdd1.countByValue() + "\n") 16/08/18 11:51:16 INFO DAGScheduler: Job 11 finished: countByValue at Function.scala:48, took 0.031726 s Map(monkey -> 1, coffee -> 2, panda -> 1, tea -> 1) 16/08/18 11:51:16 INFO SparkContext: Starting job: takeOrdered at Function.scala:50 takeOrdered rdd1.takeOrdered(10).take(100).foreach(println) 16/08/18 11:51:16 INFO DAGScheduler: Job 12 finished: takeOrdered at Function.scala:50, took 0.026160 s coffee coffee monkey panda tea 16/08/18 11:51:16 INFO SparkContext: Starting job: takeSample at Function.scala:52 aggregate 这个要重点介绍一下: Spark文档中aggregate函数定义如下 def aggregate[U](zeroValue: U)(seqOp: (U, T) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): U Aggregate the elements of each partition, and then the results for all the partitions, using given combine functions and a neutral “zero value”. This function can return a different result type, U, than the type of this RDD, T. Thus, we need one operation for merging a T into an U and one operation for merging two U’s, as in scala.TraversableOnce. Both of these functions are allowed to modify and return their first argument instead of creating a new U to avoid memory allocation. seqOp操作会聚合各分区中的元素,然后combOp操作把所有分区的聚合结果再次聚合,两个操作的初始值都是zeroValue. seqOp的操作是遍历分区中的所有元素(T),第一个T跟zeroValue做操作,结果再作为与第二个T做操作的zeroValue,直到遍历完整个分区。combOp操作是把各分区聚合的结果,再聚合。aggregate函数返回一个跟RDD不同类型的值。因此,需要一个操作seqOp来把分区中的元素T合并成一个U,另外一个操作combOp把所有U聚合。 val rdd5 = sc.parallelize(List(1,2,3,4)) val rdd6 = rdd5.aggregate((0, 0)) ((x, y) =>(x._1 + y, x._2+1), (x, y) =>(x._1 + y._1, x._2 + y._2)) print ("aggregate action : " + rdd6 + "\n" ) 我们看一下结果: 16/08/18 11:51:16 INFO DAGScheduler: Job 16 finished: aggregate at Function.scala:57, took 0.011686 s aggregate action : (10,4) 16/08/18 11:51:16 INFO SparkContext: Invoking stop() from shutdown hook 我们可以根据以上执行的例子来理解aggregate 用法: 第一步:将rdd5中的元素与初始值遍历进行聚合操作 第二步:将初始值加1进行遍历聚合 第三步:将结果进行聚合 根据本次的RDD 背部实现如下: 第一步:其实是0+1 1+2 3+3 6+4 然后执行:0+1 1+1 2+1 3+1 此时返回(10,4) 本次执行是一个节点,如果在集群中的话,多个节点,会先把数据打到不同的分区上,比如(1,2) (3,4) 得到的结果就会是(3,2) (7,2) 然后进行第二步combine就得到 (10,4) 这样你应该能理解aggregate这个函数了吧 以上就是对常用的Transformations 和Actions介绍,对于初学者来说,动手代码实践各个函数,才是明白其功能最好的方法。 PS :源码 Spark的这些事系列文章: Spark的这些事<一>——Windows下spark开发环境搭建 Spark的这些事<二>——几个概念 Spark的这些事<三>——spark常用的Transformations 和Actions

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册