关于scala:Scala技术与架构

1. 前言Scala是综合了面向对象个性与函数式个性的程序设计语言,是由EPFL主导与保护的开源高级编程语言,Scala提供的动态类型机制能够让程序在一些简单的运行场景中防止一些缺点的呈现,Scala同时反对JVM、JavaScript以及其余有待反对的运行时环境,Scala同时也提供弱小的、开源的、基于生态的反对库,开发者应用Scala的反对库能开发出高效与高性能的利用零碎。 1.1 运行环境Scala反对的运行时环境形容如下所示: JVMScala反对Java虚拟机的运行时环境,应用Scala的编译环境能够将Scala的程序语言编译成合乎JVM执行规范的文件格式,Scala能够间接援用Java语言的类办法、变量以及属性,Scala的打包归档格局应用JAR规范规格 JavaScriptScala反对JavaScript前端或者Nodejs后端的运行时环境,应用Scala的编译环境能够将Scala的程序语言编译成合乎ECMAScript执行规范的文件格式 Scala NativeScala反对LLVM类型的机器语言的编译,利用于嵌入式设施相干的高中低级别的操作系统的来自底层应用逻辑的运行时环境 1.2 全栈技术从传统的应用软件零碎的分层架构的角度剖析,Scala将提供全栈式的技术栈,开发者能够应用Scala生态体系开发出全栈式的技术框架、工具集以及大规模的分布式应用软件系统。目前,Scala被宽泛地使用于不同的业务畛域,其反对的技术栈分类如下所示: 异步、并发、分布式编程异步以及响应式编程,次要提供异步编程框架,实现高性能的并发编程模型分布式音讯零碎以及微服务,次要提供分布式的消息中间件或者分布式的微服务服务(Apache Kafka应用Scala开发)调度器,次要提供定时或者定时距离的任务调度框架 大数据处理数据源与连接器,用于连贯数据存储端与数据处理端,实现数据的读写操作,或者用于数据源采集数据可视化,用于解决汇总剖析的数据,以及综合不同的汇总剖析的数据,用于用户界面的数据审计以及展现分布式计算,用于实现大规模数据的剖析与计算,例如Apache Spark 计算迷信算法与数据结构,用于图计算、单纯函数式计算、非凡数据结构的计算缓存,用于本地数据缓存或者连贯分布式数据缓存 配置、日志、测试、监控 命令行解析,用于服务器端解析近程保护工具的输出命令行,实现近程系统维护环境配置,用于保护服务器或者利用零碎的配置,实现配置的集中保护日志,用于利用零碎的日志记录或者日志采集性能监控,用于分布式应用的拜访链路的追踪、数据不同维度的统计分析的监控测试,提供实现零碎功能测试的框架 数据库、索引、搜寻数据库,用于时序数据库、图数据库、数据源连接器提供查问与拜访操作索引与搜寻,应用异步操作或者更优的索引技术改善Elasticsearch索引零碎的查问性能 部署、虚拟化、云计算云部署,用于大规模的云计算零碎、云原生零碎的部署FAAS,用于云计算、云服务中提供Serverless服务类型的Lambda式编程版本治理,用于工程项目的版本治理与保护虚拟化与容器化,用于容器镜像的创立与服务编排 开发工具构建工具,用于工程项目的构建代码剖析,用于代码生成、代码剖析与审计代码编辑,用于实现服务器版的IDE、本地版IDE的插件、记事本代码格式化,用于代码款式的保护依赖库治理,用于工程项目依赖库或者库版本的治理代码重构,用于代码优化与重构打包公布,用于工程项目的打包与公布控制台信息,用于提供控制台信息的输入REPL,用于实现脚本或者交互式解析器动态资源,用于实现网站或者文档相干动态资源的管控 图像与多媒体音频与音乐,用于音频文件的编辑或者合成视频与图像处理,用于实现图像的剖析与解决,与JVM轻易集成提供实现视频解决性能 数学、金融、数据迷信、生物信息生物信息,用于大规模基因信息数据的剖析密码学与哈希,用于区块链以及数据安全的加密解密经济、金融与加密货币,用于比特币的实现、高性能的寰球货币的转换计算自然语言解决,用于自然语言的剖析与解决数字特色计算,用于数学运算相干的数字解决与计算概率、统计学与机器学习,用于预测剖析、统计分析、概率分析、监督型或者非监督型的机器学习 挪动、桌面、游戏开发图形接口与游戏开发,用于创立JVM类型的桌面端利用、2D或3D游戏引擎、图向量计算挪动利用,用于安卓端的利用开发 操作系统、硬件、机器人文件系统解决,用于文件系统中解决文件的读写操作硬件与模仿,用于智能硬件的开发网络,用于操作系统中网络层利用或者网络层工具的开发 文本、格局、压缩 文件归档与压缩,用于实现文件的归档与压缩CSV,用于数据表格的读写操作JSON,用于JSON文本格式的创立、编辑以及解析文本编辑器,用于文本的操作、转换以及格式化PDF,用于PDF文件的创立、编辑以及解析序列化,用于协定传输内容的序列化与反序列化YAML,用于YAML文本格式的创立、编辑以及解析 工夫、地位、测量工夫与日期,用于工夫与日期的解决地位,用于地理位置的计算与解决测量,用于工业畛域的计量与测量相干的计算 Web开发管理系统,用于内容、信息、资产零碎的治理权限治理,用于提供用户的集中受权与鉴权服务电子邮件,用于实现电子邮件协定表单与验证,用于实现web界面表单的提交与合法性校验HTTP,用于反对服务器端或者客户端的HTTP协定的交互国际化,用于反对web界面中不同的地区语言语义,用于解析语法语义模板,用于实现web界面组件的模板定义或者模板解决API,用于开发API服务或者对接第三方的API服务路由,用于前端页面显示门路的跳转前端,用于前端框架开发文档,用于解析XML、HTML中元素或文档的解析JSON,用于反对JSON文本类型的编辑、解析

September 5, 2022 · 1 min · jiezi

关于scala:聚合翻译Multi-Platform-Translate-Tool-in-Python

Multi Platform Translate Tool in Python https://pypi.org/project/mult... https://github.com/Lyndon1994... Translate is a simple but powerful translation tool written in python with support for multiple translation providers. By now we offer integration with Baidu, Bing, Deepl, Google, MyMemory, Tencent, Youdao translation APIs. It is forked from translate, and it is compatible with this pack. Why Should I Use This?The biggest reason to use translate is to make translations in wox and alfred quickly, and I would like to see the translation results of various platforms and choose the best one. I want to share with you, and it supports concurrent request for multiple platform translation results. ...

August 2, 2022 · 3 min · jiezi

关于scala:Scala与Java中与equals用法总结

在Java和Scala语言中,==和equals的用法是略有不同的,如果不比照学习,容易产生困惑,当初来比照总结。 一、Java当中的数据类型和“==”的含意: 根本数据类型:byte,short,char,int,long,float,double,boolean。他们之间的比拟,利用双等号(==),比拟的是他们的值。 援用数据类型:当他们用(==)进行比拟的时候,比拟的是他们在内存中的寄存地址(确切的说,是堆内存地址)。 注:对于第二种类型,除非是同一个new进去的对象,他们的比拟后的后果为true,否则比拟后后果为false。因为每new一次,都会从新开拓堆内存空间。 二、Java中equals()办法介绍: JAVA当中所有的类都是继承于Object这个超类的,在Object类中定义了一个equals的办法,equals的源码是这样写的: public boolean equals(Object obj) { //this - s1 //obj - s2 return (this == obj); } 能够看到,这个办法的初始默认行为是比拟对象的内存地址值,一般来说,意义不大。所以,在一些类库当中这个办法被重写了,如String、Integer、Date。在这些类当中equals有其本身的实现(个别都是用来比拟对象的成员变量值是否雷同),而不再是比拟类在堆内存中的寄存地址了。 所以说,对于复合数据类型之间进行equals比拟,在没有覆写equals办法的状况下,他们之间的比拟还是内存中的寄存地位的地址值,跟双等号(==)的后果雷同;如果被复写,依照复写的要求来。 咱们对下面的两段内容做个总结吧: == 的作用: 根本类型:比拟的就是值是否雷同 援用类型:比拟的就是地址值是否雷同 equals 的作用: 援用类型:默认状况下,比拟的是地址值。 注:不过,咱们能够依据状况本人重写该办法。个别重写都是主动生成,比拟对象的成员变量值是否雷同 在Scala中对于==和equals办法的应用有所不同,==的实现很用心,当调用==操作符时,会首先查看左侧是否为null,若不为null,则调用equals办法,而调用的equals办法的具体比拟逻辑,则取决于左侧参数的类型,对于根底数据类型以及String类型来说,equals办法的逻辑次要为比拟两者的值是否相等。所以在Scala中,当你调用==或者equals办法时,更多的失去是二者的值是否相等(除非你比拟的对象类型重写了equals办法,实现了本人的比拟逻辑),而且很显著应用==比equals更平安,因为==会首先确认左侧对象是否为null,防止了空指针异样。如果你想比拟两个对象的援用是否相等,Scala为用户提供了eq办法。总结如下: ==、equals的作用: 比拟值相等性,==会首先判断左侧对象是否为null,而后调用对象类型的equals办法,更平安。 Eq办法的作用: 比拟援用相等性。 关键词:java培训

May 6, 2022 · 1 min · jiezi

关于scala:scala安装及环境配置

Scala 语言能够运行在Window、Linux、Unix、 Mac OS X等零碎上。 Mac OS X 和 Linux 上装置 Scala第一步:Java 设置确保你本地曾经装置了 JDK 1.5 以上版本,并且设置了 JAVA_HOME 环境变量及 JDK 的 bin 目录。 咱们能够应用以下命令查看是否装置了 Java: $ java -versionjava version "1.8.0_31"Java(TM) SE Runtime Environment (build 1.8.0_31-b13)Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)$接着,咱们能够查看是否装置了 Java 编译器。输出以下命令查看: $ javac -versionjavac 1.8.0_31$接下来,咱们能够从 Scala 官网地址下载 Scala 二进制包,本教程咱们将下载 2.11.7版本,如下图所示: 解压缩文件包,可将其挪动至/usr/local/share下: mv scala-2.11.7 scala # 重命名 Scala 目录mv /download/scalapath /usr/local/share # 下载目录须要按你理论的下载门路批改环境变量,如果不是管理员可应用 sudo 进入管理员权限,批改配置文件profile: vim /etc/profile ...

April 21, 2022 · 1 min · jiezi

关于scala:Scala-中的底类型bottom-types

在Scala中存在两个比拟非凡的类,Scala.Null和Scala.Nothing。它们是Scala面向对象的类型零碎用于解决一些“极其状况”的非凡类型。 Null类是null援用的类型,他是每个援用类(即继承自AnyRef的类)的子类,null值能够用来给援用类初始化。然而Null并不兼容于值类型,即你不可能将null赋值给一个整数变量: val i: Int = null 以上写法是不对的。 Nothing位于Scala类继承关系的最底部,它是每个其余类型的子类型,并且,不存在这个类型的任何值。那么,Nothing类型的意义何在呢? Scala中的底类型(bottom types)作为参数类型。在Scala的List中有一个非凡的存在,Nil,如果应用过Nil你就会发现,Nil实际上就是一个List[Nothing]。所以Nil能够与任何类型的元素进行汇合的相干操作,例如1 ::Nil,”abc” :: Nil,最终失去的汇合后果会依据增加的元素类型决定,因为Nothing是任何类的子类,它能够被归为任何List中去。 非正常终止信号在Scala中抛出异样跟Java一样,须要创立一个异样对象而后用throw关键字将它抛出: throw new IllegalArgumentException 并且,在Scala中,抛出异样的动作throw是一个有后果类型的表达式,这个后果的类型就是Nothing。如下示例: val half:Int = If ( n % 2 == 0) n / 2 else throw new RuntimeException(“n must be even”) 在这段代码中,如果n是偶数,那么half会被赋值为n的一半,如果n不是偶数那么half被初始化之前,就会有异样抛出。而你如此写不必放心half的类型问题,因为技术上讲,抛出异样这个表达式的类型是Nothing。在这个场景下,if的一个分支计算出某个值,而另一个分支抛出异样并计算出Nothing,整个if表达式的类型就是那个计算出某个值的分支。 再举例来说,在Scala的规范类库中Predef对象有一个error办法,其定义如下: def error(message:String):Nothing = throw new RuntimeException(message) error办法的返回值类型是Nothing,这通知应用方该办法并不会失常返回,它会抛出异样。对error的应用如下: def divide(x: Int, y: Int): Int = if (y != 0) x / y else error(“can’t divide by zero”) 这里的x/y条件判断的then分支的类型为Int,而else分支类型为Nothing,因为Nothing是Int的子类型,整个条件判断表达式的类型就是Int,正如办法申明要求的那样。 关键词:大数据培训

April 18, 2022 · 1 min · jiezi

关于scala:Scala-下划线用法总结

Scala 是一门以 java 虚拟机(JVM)为运行环境并将面向对象和函数式编程的最佳个性联合在一起的动态类型编程语言。scala 单作为一门语言来看, 十分的简洁高效,在 Scala 中存在很多让代码更加简洁的语法,下划线“_”便是其中一个。下划线的广泛用法总结如下: 用于变量初始化在 Java 中,能够申明变量而不用给出初始值,在 Scala 中,变量在申明时必须显示指定,能够应用下划线对变量进行初始化。而且该语法只实用于成员变量,不适用于局部变量。例: class Student{//String类型的默认值为nullvar name:String=-用于导包引入导包引入时应用_导入该包下所有内容,类比 Java 中的*。例如: //Javaimport java.util.*1/ScalaImport java.uti.3.用于将办法转变为函数 在 Scala 中办法不是值,而函数是。所以一个办法不能赋值给一个 val 变量,而函数能够。办法能够转换为函数赋值给变量,例: //将println办法转换成函数。井赋值给pval p = printin_ 用于模式匹配模式匹配中能够用下划线来作为 Java 中 default 的类比应用,也能够在匹配汇合类型时,用于代表汇合中元素,例:val t =(1,2,3)printIn(t._1, t_2,t._3) str match{case "1" => printIn("match 1"7)case_=>printin("match default")/匹配以0结尾,长度为三的列表expr match [case List(O,, ) => printin("found it)case _=>//苋配以0结尾,长度任衰的列表expr match {case List(0,_) =>printin("found it)case_=>)//匹配元组元素expr match [case (0,)=> printin("found it)case_ =>1/将首元素赋值给head变量val Lst(head,_)= List(a7)用于拜访 tuple 元素例: val t =(1,2,3)printIn(t._1, t_2,t._3) ...

April 1, 2022 · 1 min · jiezi

关于scala:Scala一门特立独行的语言

<!-- Scala,一门「特立独行」的语言! --> 入门 Spark 的路上很难不接触 Scala 。 Scala 仿佛是为 java 提供了很多『相似函数式编程』的语法糖,这里记录一下这个语言独特的中央分享给读者敌人们。 参考资料次要有: 曹洁 . Spark大数据分析技术(Scala版)[M]. 北京航空航天大学出版社, 2021. ISBN:9787512433854陈欢 , 林世飞 . Spark最佳实际[M]. 人民邮电出版社, 2016. ISBN:9787115422286Scala 根本思维与注意事项Sacla 即 Scalable Language ,正如其名,是一门可伸缩的编程语言: 基于 java 的虚拟机( Scala 会被编译成 JVM 字节码)然而既能够当脚本应用,又能够结构大型零碎是动态语言,然而能够像动静语言那样反对交互式编程面型对象:每一个值都是对象,每一次运算都是一次办法调用函数式编程:所有函数都是对象,函数是“一等公民”Scala 中简直一切都是表达式scala 是解释器, scalac 是编译器;能够间接 scala test.scala ,也能够 scalac test.scala & scala test (先把源码编译为字节码,再把字节码放到虚拟机中解释运行)。还可用输出 scala 进入替换编程界面。 所以要留神的是,须要先装置 JDK ,并且设置好环境变量 JAVA_HOME 。此外,更加重要的是, Scala 小版本兼容:2.12.x 与 2.13.x 这两者不兼容,2.12.10 与 2.12.11 才兼容。 最根本的语法示例类型的申明、控制结构(for、模式匹配、case)// 变量val two: Int = 1 + 1var one: Int = 1var one: String = 'one'// 函数def addOne(x: Int): Int = x + 1def add(x: Int, y: Int): Int = { x + y}// 局部控制结构var filename = if (!args.isEmpty) args(0) else "default.txt"for (i <- 1 to 4) println("iteration " + i)1 to 4 是 [1,2,3,4] ,而 i until 4 是 [1,2,3] 。 ...

July 12, 2021 · 5 min · jiezi

关于scala:使用-Scala-宏解决对象转换

背景在 GrowingIO 服务端的开发中,咱们应用 gRPC 进行微服务之间的数据通信,每个提供服务的我的项目,都要定义一套本人的 Protobuf 音讯格局,而后利用 protoc 去生成对应语言的适配代码。在咱们保护的我的项目中,次要应用 Scala 语言来实现各个服务,每个服务都会定义一套本人的畛域模型(个别是一些 case class),而 protoc 默认生成的 JVM 平台的代码是 Java 语言的,对应的 Protobuf 音讯格局与 Scala 我的项目中定义的畛域模型会存在一些对应关系,并且他们的属性往往会高度一致。当咱们须要在这两种类型做数据转换时,会呈现许多 protobuf-java 和 scala case class之间的转换代码。 个别状况下,protobuf-java 和 Scala 之间都能找到对应类型,比方 java.util.List 和 Seq/List/Array,Timestamp 和 ZonedDateTime,同时一些 Scala 中 Option 类型也能够用 protobuf 是一封装类型去示意,比方 Option[String] 能够用 StringValue 去示意。因为每个类型都有本人对应的个性,类型嵌套又会减少极大地减少复杂度,咱们始终在找一个通用的转换计划,应用起来类型平安,并尽可能地省掉臃肿无味的代码。 参考了https://github.com/playframework/play-json 的 Reader、Writer 设计设计理念和 https://github.com/scalalandio/chimney用 Scala 宏对类型转换的解决形式,咱们最终应用了 Scala 宏联合隐式参数 DSL 设计的思路实现了 https://github.com/changvvb/scala-protobuf-java 一套解决方案。 计划成果咱们先在这里定义一个 case class User 和 Protobuf UserPB 来比照应用该计划前后的成果。 case class User ( id:Long, name:String, phoneNumber: Option[String], hobbies: Seq[String])message UserPB ( int64 id = 1, string name = 2, google.protobuf.StringValue phone_number = 3, repeated string hobbies = 4)如果咱们本人手写 scala case class 到 protobuf-java 的转换,成果将是这样的: ...

June 28, 2021 · 3 min · jiezi

关于scala:Scala系列

Scala - 初识ScalaScala - 变量、块、办法、函数的定义以及数据类型Scala - 流程管制Scala - 类的定义Scala - 形象、继承、多态Scala - 伴生对象Scala - 特质TraitScala - 数组Scala - 序列Scala - 汇合Scala - 映射Scala - 模式匹配Scala - 隐式转换Scala - 泛型

May 17, 2021 · 1 min · jiezi

关于scala:Scala-泛型

泛型上面是相似于java的泛型,有三个类Shape(形态)、Rectangle(长方形)、Square(正方形)。Shape是Rectangle的父类,Rectangle是Square的父类。所以咱们定义变量的时候,能够申明他为Shape类型,在new的时候给具体的类型。Draw1这里有个泛型T,咱们能够看到定义变量的时候,这里的类型是不能有父子类关系的。 object GenericDemo { def main(args: Array[String]): Unit = { val shape1: Shape = new Shape() var shape2: Shape = new Rectangle() var shape3: Shape = new Square() val draw1: Draw1[Shape] = new Draw1[Shape]() // val draw2: Draw1[Shape] = new Draw1[Rectangle]() // error // val draw3: Draw1[Shape] = new Draw1[Square]() // error }}class Shape {}class Rectangle extends Shape {}class Square extends Rectangle {}class Draw1[T]() {}协变和逆变下面不能编译是因为Draw1[Shape]和new Draw1[Rectangle]并没有父子关系,Scala通过协变能够让他们有父子关系:在泛型T后面加一个+ class Draw2[+T]() {}而后在main函数中就能够调用了: ...

May 17, 2021 · 2 min · jiezi

关于scala:Scala-隐式转换

有时候咱们看scala代码的时候,会发现明明没有这个类的类型或者函数,甚至是没有这个类,编译器不仅没有报错,程序还能够失常运行,其实这里就用到了scala的隐式转换。 隐式函数当咱们调用一个对象的办法的时候,然而这个对象并没有这个办法,此时就会触发隐式转换,会把这个对象偷偷的转换为具备这个办法的对象。比方上面的例子,小鸡能够走路也能够跑,然而它也想像小鸟一样飞,然而它有没有这个性能。咱们能够在不对小鸡整改的根底上,引入ChickenImplicit,让小鸡能够隐式的调用Bird的fly办法,让它能够像小鸟一样飞。 object ImplicitDemo1 { def main(args: Array[String]): Unit = { import ChickenImplicit._ val chicken = new Chicken() chicken.work() chicken.run() // 隐式转为Bird,并调用Bird的fly办法 chicken.fly() }}class Chicken() { def work(): Unit = { println("小鸡在走") } def run(): Unit = { println("小鸡在跑") }}class Bird { def fly(): Unit = { println("小鸟在飞") }}object ChickenImplicit { implicit def chicken2Bird(c: Chicken): Bird = new Bird()}下面是额定的定义ChickenImplicit,然而有时候咱们能够间接在同一个类里定义,这样局不必加import,具体用哪种还是要看理论场景。 object ImplicitDemo2 { def main(args: Array[String]): Unit = { val chicken = new Chicken2() chicken.work() chicken.run() // 隐式转为Bird,并调用Bird的fly办法 chicken.fly() } implicit def chicken2Bird(c: Chicken2): Bird2 = new Bird2()}class Chicken2() { def work(): Unit = { println("小鸡在走") } def run(): Unit = { println("小鸡在跑") }}class Bird2 { def fly(): Unit = { println("小鸟在飞") }}隐式参数比方咱们要调用办法,打印咱们传递的参数,咱们是这样写的: ...

May 17, 2021 · 1 min · jiezi

关于scala:Scala-模式匹配

scala的模式匹配,关键字是match,相似于java的switch,然而性能更弱小,咱们看看scala模式匹配的几种类型。 常量匹配咱们这里以字符串为例。关键字是match,case前面通过=>来分隔匹配的模式以及匹配后的代码。case是各个分支,如果匹配胜利,就会执行相应的代码块,这里的代码块能够不必大括号。如果都不匹配,那旧执行case _里的代码块,绝对于java的default。 val str: String = "b"val result = str match { case "a" => 1 case "b" => println("b") 2 case "c" => 3 case _ => 0}println(result) // 2如果case b局部改以下代码,因为if里的条件不合乎,那他会到case _ ,返回0。 case "b" if(str.equals("c")) => println("b")类型匹配与下面略微有点不同的是,类型后面要加一个参数,这个参数能够在前面的代码块里能够援用。 def main(args: Array[String]): Unit = { val array: Array[Any] = Array("a", 1, true, Array(1)) for (e <- array) { matchCase(e) }}def matchCase(v: Any): Unit = { v match { case a: Int => println(s"Int $a") case b: String => println(s"String $b") case c: Boolean => println(s"Boolean $c") case _ => println(s"Nothing") }}运行后果如下: ...

May 14, 2021 · 3 min · jiezi

关于scala:Scala-映射

映射分为可变映射mutable.Map和不可变映射Map。 Map定义Map,通过 -> 合乎连贯键值对。 // 定义val map = Map("a" -> 1, "b" -> 2, "c" -> 3)println(map) // Map(a -> 1, b -> 2, c -> 3)读取元素,通过get的话,当有值的时候,失去Some,没有值的话,失去None。因为是Some,须要再加一个get才能够获取具体的值,也能够通过(key)失去具体的值。如果不确定值是否存在,能够用getOrElse办法,前面带默认值,没有对应的值的话,就返回这个默认值。 // 读取println(map.get("a")) // Some(1)println(map.get("a").get) // 1println(map("a")) // 1println(map.get("d")) // Noneprintln(map.getOrElse("d", 0)) // 0循环遍历:能够间接打印每个键值对,也能够在循环里通过_1,_2获取键值对。能够通过keys获取键汇合,也能够通过values获取值汇合 map.foreach(println) // (a,1) (b,2) (c,3)map.foreach(e => println(e))// (a,1) (b,2) (c,3)map.foreach(e => { println(e._1 + "->" + e._2) // a->1 b->2 c->3})map.keys.foreach(println) // a b cmap.values.foreach(println) // 1 2 3mutable.Map通过mutable.Map来定义 ...

May 13, 2021 · 1 min · jiezi

关于scala:Scala-集合

汇合分为可变汇合mutable.Set和不可变汇合Set。 Set// 定义val set1 = Set(1, 2, 3, 1, 2, 3)println(set1) // Set(1, 2, 3)// 新增val set2 = set1.+(4)println(set2) // Set(1, 2, 3, 4)val set3 = set1 + 4println(set3) // Set(1, 2, 3, 4)// 删除val set4 = set3 - 1println(set4) // Set(2, 3, 4)// 加汇合val set5 = Set(2, 3, 4, 5)val set6 = set1 ++ set5println(set6) // Set(5, 1, 2, 3, 4)// 循环set6.foreach(println)// 并集val set7 = Set(1, 2, 3) union (Set(2, 3, 4))println(set7) // Set(1, 2, 3, 4)// 差集val set8 = Set(1, 2, 3) diff (Set(2, 3, 4))println(set8) // Set(1)// 交加val set9 = Set(1, 2, 3) intersect (Set(2, 3, 4))println(set9) // Set(2, 3)mutable.Set循环、并集、差集、交接同上,这里不做累述 ...

May 13, 2021 · 1 min · jiezi

关于scala:Scala-序列

scala的汇合也分为不可变汇合和可变汇合。汇合包含序列Seq、汇合Set、映射Map,这几个也是分为不可变和可变的。 不可变List定义List,包含List的apply、:: Nil、以及:::来定义。Nil是空的汇合,::是head元素和tail列表组成一个新的列表,而且这个是从前面开始计算的,所以上面的也绝对于3::Nil先计算,而后是2::(3 :: Nil),最初是1::(2::(3 :: Nil))。如果head是一个List,那用::的话,第一个元素还是List,所以要用:::来造成新的列表,能够看看上面的list3、list4。 // 定义Listval list1: List[Int] = List(1, 2, 3)val list2: List[Int] = 1 :: 2 :: 3 :: Nilval list3: List[Any] = list1 :: list2val list4: List[Int] = list1 ::: list2println(list1) // List(1, 2, 3)println(list2) // List(1, 2, 3)println(list3) // List(List(1, 2, 3), 1, 2, 3)println(list4) // List(1, 2, 3, 1, 2, 3)a读取List: // 取指定地位println(list1(0)) // 1// 取第一个无素println(list1.head) // 1// 取第一个无素后的残余列表println(list1.tail) // List(2, 3)// 取第二个无素println(list1.tail.head) // 2// 取最初一个无素println(list1.last) // 3// 取最初一个无素后的残余列表println(list1.init) // List(1, 2)// 倒序println(list1.reverse) // List(3, 2, 1)// 获取前N个元素println(list1.take(2)) // List(1, 2)// 字符串拼接println(list1.mkString("-")) // 1-2-3新增元素: ...

May 13, 2021 · 2 min · jiezi

关于scala:Scala-数组

数组分为可变数组ArrayBuffer和不可变数组Array。 ArrayArray是不可变数组,这里的不可变是指对象的援用不能变,他的长度是固定的不能变的,然而他的元素却是能够更改的。定义一个不可变数组: // 长度为3的数字,默认都是0,[]里是类型,()里是长度val arr1: Array[Int] = new Array[Int](3)// 间接定义数组的元素,这里就是间接调用apply办法了val arr2: Array[Int] = Array(1, 2, 3)读取、批改: println(arr1(0)) // 0println(arr2(0)) // 1arr1(0) = 1arr2.update(0, 11)println(arr1(0)) // 1println(arr2(0)) // 11转为字符串,并用-连贯: println(arr2.mkString("-")) // 1-2-3求最大值、最小值、求和: println(arr2.sum) // 16println(arr2.max) // 11println(arr2.min) // 2往前面或前面新增元素,因为是不可变数组,所以返回的是新的数组。 .+:():办法,加号在后面,所以往前面加元素.:+():办法,加号在前面,所以往后面加元素+::符号,加号在后面,所以往前面加元素:+:符号,加号在前面,所以往后面加元素val arr3 = arr2.+:(10).:+(4)println(arr3.mkString("-")) // 10-11-2-3-4val arr4 = 8 +: 9 +: arr3 :+ 5 :+ 6println(arr4.mkString("-")) // 8-9-10-11-2-3-4-5-6遍历数组:until、to 、indices是取索引,而后通过索引取值。until和to的区别是to是等于数组的长度until是小于。前面几个都是间接取数组的元素。 for (i <- 0 until arr2.length) print(arr2(i) + "-") // 11-2-3-println()for (i <- 0 to arr2.length - 1) print(arr2(i) + "-") // 11-2-3-println()for (i <- arr2.indices) print(arr2(i) + "-") // 11-2-3-println()for (i <- arr2) print(i + "-") // 11-2-3-println()arr2.foreach((e: Int) => print(e + "-")) // 11-2-3-println()arr2.foreach(println) // 11 2 3ArrayBufferArrayBuffer是可变数组,所以能够对他进行新增、删除等操作。 ...

May 12, 2021 · 2 min · jiezi

关于scala:Scala-特质Trait

特质Trait在scala中,有一个既相似java接口的又相似java抽象类的概念,叫做特质Trait。咱们能够把他当作接口来用,应用形式和java的接口相似,也能够把他当作抽象类应用,应用形式就和java的抽象类相似。然而不论用接口还是形象的形式,都是应用关键字extends。接口的形式: trait ScalaTrait { def printInfo(): Unit}class ScalaClass extends ScalaTrait { override def printInfo(): Unit = { println("ScalaClass") }}object ScalaClass { def main(args: Array[String]): Unit = { val scalaClass = new ScalaClass scalaClass.printInfo() }}抽象类的形式: trait ScalaTrait2 { def printInfo(): Unit def printInfo2(): Unit = println("printInfo2")}class ScalaClass2 extends ScalaTrait2 { override def printInfo(): Unit = { println("ScalaClass2") }}object ScalaClass2 { def main(args: Array[String]): Unit = { val scalaClass = new ScalaClass2 scalaClass.printInfo() scalaClass.printInfo2() }}多个Trait继承抽象类是不能多继承的,然而Trait是能够多继承的,多个Trait间接用with关键字。上面例子中,ScalaClass3 既有ScalaTraitA01的办法实现,也有ScalaTraitA02的办法实现。 ...

May 11, 2021 · 2 min · jiezi

关于scala:Scala-伴生对象

伴生对象和伴生类在后面的文章中,可能也有人留神到main办法并没有像java的static关键字,而且运行main办法的类定义的是object。object定义的类和class定义的类名字还能够一样。比方class ScalaObject和object ScalaObject,咱们能够说object ScalaObject是class ScalaObject的伴生对象,class ScalaObject是object ScalaObject的伴生类。伴生对象和伴生类能够互相拜访公有的属性和办法。在scala中定义伴生对象的属性和办法: object ScalaObject2 { var str: String = "str" def fun(): Unit = { println("fun") }}编译后会看到有ScalaObject2和ScalaObject2$两个class文件。ScalaObject2反编译如下,这里有3个静态方法,一个是咱们下面定义的fun,另外一个就是str的set和get办法。ScalaObject2.str就是调用get办法,ScalaObject2.str="str2"就是调用set办法。在static里能间接调用ScalaObject2..MODULE$,所以咱们晓得ScalaObject2..MODULE$也是动态的。ScalaObject2$反编译如下,从这里能够看出,他实际上是一个单例对象。构造函数用private润饰,而后又用this指向MODULE$,让MODULE$对外提供办法。在上面的例子中,str是伴生类ScalaObject的公有属性,在伴生对象ScalaObject中,是能够间接拜访的,所以伴生对象和伴生类能够互相拜访公有的属性和办法。 class ScalaObject { private var str: String = "str"}object ScalaObject { def main(args: Array[String]): Unit = { val scalaObject = new ScalaObject() println(scalaObject.str) }}单例相似java的单例模式:首先结构器默认private的,此时是不能间接通过结构器来创立这个对象,而后在伴生对象中,申明一个办法用于创立这个对象,因为伴生对象和伴生类能够相互调用公有办法,所以是能够通过结构器来创立这个对象。 object ScalaObject3 { private val scalaObject3: ScalaObject3 = new ScalaObject3 def getInstance(): ScalaObject3 = { scalaObject3 }}class ScalaObject3 private() {}而后在Test中创立一个单例,间接通过new是不行的,所以通过伴生对象来获取。运行后,能够看到两个地址是一样的。 object Test { def main(args: Array[String]): Unit = { //new ScalaObject3()//erro val scalaObject1 = ScalaObject3.getInstance() val scalaObject2 = ScalaObject3.getInstance() println(scalaObject1) println(scalaObject2) }}apply咱们在伴生对象中定义apply办法,而后间接类目+参数(有可能无参),实际上调用的是伴生对象的apply办法。比方在上面例子中,间接调用ScalaObject4("hello")实际上调用的是ScalaObject4.apply办法,所以apply是能够省略的。 ...

May 11, 2021 · 1 min · jiezi

关于scala:Scala-抽象继承多态

形象scala的形象关键字和java一样,都是abstract,而且抽象类都不能被实例化的。除了类能够定义为形象的,类的属性和办法,也能够是形象的。从上面的例子中,能够看到其实和java的抽象类定义没有什么区别 abstract class ScalaAbstract { // 形象属性,能够没有初始值,甚至不必_ var str1: String var str2: String = "str2" val str3: String val str4: String = "str4" /** * 形象办法 */ def printInfo1: Unit def printInfo2: Unit = { println(s"${str1},${str2},${str3},${str4}") }}继承和java一样,继承也是用extends关键字,概念也是同java的,包含先调用父类的结构器等。区别如下: 如果笼罩父类的非形象办法,非形象变量,在scala中要写override,在java中只是正告。形象办法,var定义的形象变量,能够不写override,也能够写。val定义的形象变量,要写override。class ScalaChild extends ScalaAbstract { /** * 能够不写override */ var str1: String = "str1" /** * 间接批改 */ str2 = "str2" /** * 必须写override */ override val str3: String = "str3" /** * 必须写override */ override val str4: String = "str4" /** * 形象办法,能够不写override */ def printInfo1: Unit = { println(s"${str1},${str2},${str3},${str4}") } /** * 必须写override */ override def printInfo2: Unit = { println(s"ScalaChild:${str1},${str2},${str3},${str4}") }}object ScalaChild { def main(args: Array[String]): Unit = { val child = new ScalaChild() child.printInfo1 child.printInfo2 }}多态咱们先看看比拟相熟的java。定义了一个抽象类JavaAnimal,蕴含一个变量name和办法eat。JavaCat和JavaDog是JavaAnimal的实现类。在main办法中通过eat办法打印。 ...

May 10, 2021 · 2 min · jiezi

关于scala:Scala-类的定义

成员变量在java中,咱们定义一个类是这样的: public class JavaPerson { private String name; private Integer age; // 省略name、age的setter和getter办法}调用是这样的: public static void main(String[] args) { JavaPerson javaPerson = new JavaPerson(); javaPerson.setAge(18); javaPerson.setName("张三"); System.out.println("姓名:" + javaPerson.getName() + ",年龄:" + javaPerson.getAge());}在scala中,会比拟简洁一点,类的定义如下,因为scala中变量的定义都要有初始值,所以咱们这边能够定义为下划线阐明是空。 class ScalaPerson { var age: Integer = _ var name: String = _}调用是这样的: val scalaPerson = new ScalaPersonscalaPerson.age = 18scalaPerson.name = "张三"println(s"姓名:${scalaPerson.name},年龄:${scalaPerson.age}")看起来咱们是间接调用对象的属性,实际上是scala暗藏了setter和getter,咱们看看反编译的代码,这个是ScalaPerson反编译后的代码,能够看到他的属性其实是private的,而后还有相似setter和getter的办法,比方age()和age_$eq()办法有时候为了兼容java框架,须要setter和getter办法,咱们只有在属性下面加@BeanProperty注解就能够用setter和getter办法了。 class ScalaPerson2 { @BeanProperty var age: Integer = _ var name: String = _}object ScalaPerson2 { def main(args: Array[String]): Unit = { val scalaPerson = new ScalaPerson2 scalaPerson.age = 17 scalaPerson.setAge(18) scalaPerson.name = "张三" println(s"姓名:${scalaPerson.name},年龄:${scalaPerson.getAge}") }}咱们晓得,scala的变量申明包含val和var,如果在类中定义val,那这个变量就是final类型的,比方下面的name通过val定义,他相似于上面的java代码,并且只有get办法。 ...

May 10, 2021 · 2 min · jiezi

关于scala:Scala-流程控制

if用if做流程管制的时候,包含单分支、双分支、多分支。比方java是这样写的。 public static void main(String[] args) { int num = 10; if (num == 10) { System.out.println("equal 10"); } if (num > 5) { System.out.println("greater than 5"); } else { System.out.println("less than 5"); } if (num < 5) { System.out.println("less than 5"); } else if (num > 20) { System.out.println("greater than 20"); } else { System.out.println("greater than 5 and less than 20"); }}Scala也是相似的: def main(args: Array[String]): Unit = { val num = 10 if (num == 10) println("equal 10") if (num > 5) println("greater than 5") else println("less than 5") if (num < 5) println("less than 5") else if (num > 20) println("greater than 20") else println("greater than 5 and less than 20")}然而Scala的表达式是有返回值的,所以他还能够这样: ...

May 7, 2021 · 3 min · jiezi

关于scala:Scala-变量块方法函数的定义以及数据类型

变量定义在java中,咱们是这样定义变量的: String str = "hello";int num = 1;在Scala中,咱们是这样定义变量的: val str: String = "hello"var num: Int = 1;这两个的区别: java是先申明变量的类型,而后定义变量的名称Scala是通过var定义变量的名称,而后在变量前面加他的类型Scala也能够不指定他的类型,那Scala会依据赋值来类型推断变量的类型。所以上面的语句就会打印int和class java.lang.String。Scala变量类型定义后,就不能对类型进行批改,所以咱们上面正文掉的语句是编译不过来的,这个和java一样。 var obj1 = 1println(obj1.getClass)//obj1 = "obj1"var obj2 = "obj2"println(obj2.getClass)//obj2 = 1valjava的final和Scala的val雷同都是用来润饰不可变的变量,如果是值类型,那这个值不能扭转,如果是对象类型,那这个对象的援用不可扭转。java的final,正文掉的语句是编译不过来的: final int fNum = 1;// fNum=2;//Cannot assign a value to final ariable 'fNum'Scala的val,正文掉的语句是编译不过来的: val fNum = 1//fNum = 2懒加载通过lazy val来定义一个懒加载 lazy val lz = {println("lazy")"lz"}println("-----")println(lz)打印后果如下,阐明在定义的时候,并没有运行打印的办法,只有在理论调用lz的时候,才会调用println("lazy")。 -----lazylz块表达式块表达式是用{}包裹起来的多个表达式,其中最初一个表达式就是这个块的返回值。上面的块表达式,x的值为1。 var x = { println("block") 1}println(x)函数的定义函数定义的时候,右边是传入的参数,左边是块表达式(如果只有一句能够省略{}),两头的符号是=>。比方咱们定义一个匿名函数: (x: Int) => x + 1给函数一个名称: var fun1 = (x:Int)=> x+1println(fun1(10))//输入11无参函数: ...

May 6, 2021 · 1 min · jiezi

关于scala:Scala-初始Scala

Scala是一门多范式的编程语言,一种相似java的编程语言,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种个性。咱们学这门语言之前,先要装置环境。 装置咱们在历史版本中抉择比拟罕用的版本,Scala 2.11.8。咱们以window为例,这里能够看到两个形式,msi和zip。如果是msi,那下载后间接下一步就好了,他会主动配置环境变量信息。如果是zip,那须要配置环境变量。 增加变量命SCALA_HOME增加到path中。测试(前提是jdk也装置胜利)在cmd中输出scala,cmd会显示以下信息: C:\Users\Administrator>scalaWelcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_291).Type in expressions for evaluation. Or try :help.IDEA装置idea默认不反对Scala,所以咱们须要装置插件,在file-settings->pulgins中搜寻Scala并装置,装置后重启失效。装置后还要对我的项目进行设置,能够间接右键点击我的项目,而后在add frameworks support中抉择scala,在create中,通过brower抉择本地装置的门路,实现scala的引入。也能够在project structure中,在Global Libraries,增加Scala SDK,通过brower抉择本地装置的门路后,把scala引入进来。 Hello Scala个别咱们会在这里建一个scala的包,并指定为Sources Root new一个scala class的时候抉择Object名称为HelloScala,并写入第一个main函数 object HelloScala {def main(args: Array[String]): Unit = { println("hello Scala")}}运行后输入:hello Scala在target中能够看到生成了两个class文件 和java比照scala是后缀是.scala,java的后缀是.java,编译后都是class文件,然而scala编译后有两个class文件。scala通过scalac编译,scala+文件名运行,java通过javac编译,java+文件名运行(这里没演示)类的申明不通,scala是object申明,java是class申明办法定义不一样,scala是通过def定义scala能够用分号或者换行来标识一行的结

April 29, 2021 · 1 min · jiezi

关于scala:数据结构与算法的实际应用根据表关系构建SQL语句

背景需要最近在我的项目中有一个场景,依据前端可视化模式传入的参数构建一组SQL语句,利用在Spark Streaming利用的数据同步中。这其实是一个已有的性能,然而发现原先的代码实现发现有较重大的问题,导致该性能在有关联查问时不可用,我通过调研之后决定从新实现。 这些SQL由一般的Lookup SQL和Spark SQL组成,Lookup SQL用于查问关联数据,SparkSQL则用于输入后果,外围问题在于如何正当组织这些表的关联关系。 PS:实现代码为Scala语言。 参数其中前端传入的参数为 case class UpdateTask( @BeanProperty id: Option[Long], @BeanProperty taskName: Option[String], @BeanProperty taskDesc: Option[String], @BeanProperty sourceInstance: Option[String], @BeanProperty targetInstance: Option[Long], @BeanProperty eventInstance: Option[Long], @BeanProperty sourceTree: Option[Seq[Long]], @BeanProperty selectSourceTree: Option[Seq[Long]], @BeanProperty targetTree: Option[Long], @BeanProperty eventTable: Option[Long], @BeanProperty tableRelation: Option[Seq[TableRelation]], @BeanProperty filterCondition: Option[String], @BeanProperty targetCalculateTableName: Option[String], @BeanProperty targetCalculate: Option[Seq[TargetCalculate]], @BeanProperty sourceTableField: Option[Seq[TableColumnInfo]], @BeanProperty sqlType: Option[Int], @BeanProperty classicSql: Option[String], @BeanProperty sinkConfig: Option[String], @BeanProperty targetPrimaryKey: Option[Seq[String]] ) extends SimpleBaseEntity所须要用的参数为 ...

March 25, 2021 · 5 min · jiezi

关于scala:Scala实现Spark环境下的决策树模型工程

一、我的项目背景在团体数据挖掘我的项目下,用户画像工程须要开发一些根底标签,如年龄、性别、婚姻状况、资产状况等标签。这些标签不能应用团体下的各个数据源来简略的解决后,失去后果作为最终评估后果,因为不同数据源的数据品质参差不齐,且各个数据源失去的后果置信度状况也不一样。因而咱们须要应用决策树+XGBoost等模型来综合预测用户标签。比方以下几种标签的决策树如图所示: 年龄段: 性别: 婚姻状况: 二、模型形象一开始,我筹备参照机器学习的PMML来实现决策树的形象性能,然而看了一整天的PMML官网文档和一大堆PMML相干的文章后,我发现这种计划对我来实现起来太过简单。机器学习的PMML文件大多都是模型代码主动生成的,不适宜咱们这种场景(咱们是要本人实现把决策树转换为PMML文件)。如果想要咱们来写生成PMML文件的代码,那么须要精通PMML的各类标签定义,以及在spark环境下怎么加载该文件,以及如何保障加载的Model是咱们想要的逻辑,这里实现起来,后续工作可能很简单。没方法,我只能思考在咱们本人的需要背景下,怎么本人写代码来实现决策树模型的形象性能。它至多包含以下几个难点: 一、如何形象决策树二、如何设计相似PMML的配置文件三、 三、性能实现四、优化计算五、我的项目总结

March 22, 2021 · 1 min · jiezi

关于scala:SparkCore实现离线IDMapping

最近在开发一个ID Mapping业务零碎——辨认数据上报中社交账号的关联关系,找到零碎中哪些社交账号属于事实世界中的同一个人。简略来讲,如果同一条上报数据中呈现了两个社交账号(比方一个手机号和一个QQ号),就认为这两个社交账号在事实世界属于同一个人。那么,如何计算这个关联关系呢? 一开始咱们解决这个问题的思路很间接:事实世界的每个人在零碎中用惟一的UUID标识,每次社交账号(Account)上报,在Redis中记录一个UUID->Account的正向索引,同时记录一个Account->UUID的反向索引。每个UUID下可能有多个社交账号,每个社交账号只会归属于一个UUID。每次收到2个社交账号相干的上报时,先通过Account->UUID的反向索引查到这两个社交账号对应的UUID,如果两个账号别离属于两个不同的UUID,就把这两个UUID合并为一个新的UUID,同时原来归属于这两个UUID的所有社交账号都归属于新的UUID;如果查到一个UUID,那么把这两个账号归属于这个UUID;如果未查到UUID,则新生成一个UUID,最初把新的正向索引和反向索引再写回Redis即可。 当然理论的ID Mapping可能有更简单的关联关系,并不是两个社交账号在同一条上报数据中呈现这么简略的逻辑,这就不在本文探讨的范畴内了。 这种形式乍一看也没什么问题,但认真想来却疏忽了一个很根本的问题:这种形式只能一直的将账号关联在一起,而不能解除关联。举例来说,给定A-B、B-C两组社交账号的关联关系,A、B、C应该全副关联在一个UUID下,此时若B点被删除,或B-C关联关系解除,零碎无奈将A和C解除关联。而这种解除关联的场景在业务零碎中也是很常见的,比方在企业的客户管理系统中,往往会记录一个客户的一些社交账号,有时企业会删除客户的一些社交账号,甚至删除某一个客户。 其实这个业务形象成一个数据结构的问题,就是典型的不相交集问题。每一个社交账号看做一个点,两个社交账号的关联关系看做两点之间的无向边,下面的问题就变成了在一个图里划分不相交集的问题。既然很难解决动态变化的图,就每天批量计算一下某一时刻所有账号的关联关系吧。本文就是要介绍一下如何用Spark的RDD API实现动态图不相交集的计算。 一、问题定义前言形容了问题的背景,这里再明确定义下本文要解决的问题。 算法输出是一张离线Hive表,每行有两个字段Pi、Pj,示意无向图中节点Pi和Pj之间存在一条边。输入同样失去一张Hive表,每行也是Pi、Pj两个字段,Pj均示意不相交集的根节点,即所有Pj雷同的行中Pi的汇合加上Pj就形成了与图中其余点不相关联的一个独立汇合。如图一所示,对于左侧的输出,计算结果将失去右侧的输入,能够看出P1、P2、P3、P6、P8、P9形成一个独立汇合,P4、P5、P7形成另一个独立汇合。 图一 算法输出与输入 二、计算过程1. 使每行数据中Pi > Pj为了保障迭代过程最终能够收敛,无妨将图中所有边都当做有向边解决,方向都是节点ID较大的节点指向节点ID较小的节点,这样最终计算失去的不相交集必是以汇合中ID最小的点为根,即所有节点都指向所在汇合中ID最小的点。因而,无妨将原始数据中的每一行当做由Pi指向Pj的有向边,若Pj>Pi,则替换Pi和Pj。如图二所示,这一步批改了第三行和第五行数据。 图二 使Pi > Pj edge_rdd = edge_rdd.map(row => if (row._1 > row._2) (row._1, row._2) else (row._2. row._1))2. 保障Pi不反复第一步解决完之后,原始数据中还会存在一个问题:多条边相交于一个ID较大的节点,这会导致ID较大的节点成为潜在的根节点。解决这个问题须要将部分相交于ID较大节点的边转化为相交于ID最小的节点。比方存在P6->P1和P6->P3两条边,这两条边交于P6,P1、P3、P6组成一个独立汇合。须要将这个关联关系转换为P6->P1和P3->P1两条边,即以P1为根节点。前一步的解决曾经保证数据中每一行都满足Pi>Pj,因而多条边交于ID较大的节点等价于多行的Pi雷同。所以只须要在保障原有关联关系的条件下将表处理为Pi不反复即可。 这一步保障了Pi中的节点不会作为根节点,所有有向边都由叶子节点指向潜在的根节点。 图三 保障Pi不反复 在算法实现上,首先将Pi雷同的行聚合在一起,而后输入这个汇合中每个点指向汇合中ID最小点的有向边。 while(edge_rdd.keys.count() != edge_rdd.keys.distinct.count()) { edge_rdd = edge_rdd.groupbykey() .flatMap(row => { val vertex_list = row._2.toSeq.sorted.distinct val result = new ArrayBuffer[(String, String)]() result.append(row => (row._1, vertex_list.head)) vertex_list.tail.foreach(vertex => result.append((vertex, vertex_list.head))) result })}从图三种能够看出,每次迭代之后,可能会产生新的Pi雷同的数据,因而须要用迭代的形式,屡次执行以上逻辑,迭代的终止条件就是Pi中的点不反复。 ...

March 15, 2021 · 3 min · jiezi

关于scala:scala复杂对象JSON互转方法

1、转jsonimport org.json4s.JsonDSL._import org.json4s.jackson.JsonMethods._import org.json4s.jackson.Serialization._import org.json4s.jackson.Serializationcase class WOE(col: String, woe: Map[String, String])implicit val formats = Serialization.formats(NoTypeHints)val testMap = Map[String, String]()testMap += ("1" -> "1.1")val a = WOE("1", immutable.Map(testMap.toList:_*))println(write(a)) 输入{"col":"1","woe":{"1":"1.1"}} 2、解析jsonimplicit val formats = Serialization.formats(NoTypeHints)val js ="""{"col":"1","woe":{"1":"1.1"}}"""val ab = parse(js).extract[WOE]println(write(ab)) 如果是List也能够implicit val formats = Serialization.formats(NoTypeHints) val b = new ListBuffer[WOE] val testMap = Map[String, String]() testMap += ("1" -> "1.1") b += WOE("1", immutable.Map(testMap.toList:_*)) b += WOE("3", immutable.Map(testMap.toList:_*)) println(write(b))val js = """ [{"col":"1","woe":{"1":"1.1"}},{"col":"3","woe":{"1":"1.1"}}] """ val ab = parse(js).extract[List[WOE]] println(ab.toString) 1、scala自带的Json解析scala 2.10(以上,其余版本不分明)自带Json解析,scala.util.parsing.json.JSONobject转json ...

March 15, 2021 · 4 min · jiezi

关于scala:scala二叉树深度优先遍历

Tree 定义简化定义Scala Tree构造,蕴含两个局部: Branch和Tree。为了简化数据结构,Branch只蕴含 Tree类型的 左节点 和 右节点, Leaf蕴含具体 Value sealed trait Tree[+A]case class Leaf[A](value: A) extends Tree[A]case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]深度优先遍历 DFS树的遍历右两种形式: 深度优先广度优先这里用DFS 实现,深度优先搜寻属于图算法的一种,英文缩写为DFS即Depth First Search,其过程简要来说是对每一个可能的分支门路深刻到不能再深刻为止,而且每个节点只能拜访一次。 具体搜寻程序能够参考附图 搜寻根节点 左子树搜寻以后树的左子树搜寻以后树的左子树返回父节点,搜寻父节点 右子树搜寻以后树的左子树返回父节点,搜寻父节点 右子树返回父节点, 返回父节点,返回父节点,搜寻右子树…. 咱们从一道题来相熟Scala遍历操作,求Scala树中节点总数依照DFS 思维实现代码如下 def countNodes[A](tree: Tree[A]): Int = { def go[A](tree: Tree[A], sum: Int): Int = tree match { case Leaf(v) => sum + 1 //叶子节点 sum+1 case Branch(left, right) => sum + 1 + go(left, 0) + go(right, 0) //分支节点 sum = sum + 1 + 左子树节点总数 + 右子树节点总数 case _ => 0 } go(tree, 0) //递归 }联合【Scala笔记——道】Scala List HOF foldLeft / foldRight 中讲到的List fold思维 ...

March 15, 2021 · 2 min · jiezi

关于scala:六Scala隐式转换和泛型

1.隐式转换1.1 什么是隐式转换?看如下示例 object Scala_Transform { def main(args: Array[String]): Unit = { val byte_num:Byte = 21 val int_num:Int = byte_num println(int_num) }}这个可能失常打印,因为可能编译器可能进行主动转换,但如果代码改货色,由int转换成byte object Scala_Transform { def main(args: Array[String]): Unit = { val int_num:Int = 21 val byte_num:Byte = int_num //这里会出错 println(byte_num) }}出错起因由Int到Byte没有间接的关系,编译器找不到对应的转换方法。那么咱们提供一个 object Scala_Transform { def main(args: Array[String]): Unit = { // int转换成byte的办法 def itbFun(x:Int):Byte = { x.toByte } val int_num:Int = 21 val byte_num:Byte = itbFun(int_num)//这里会出错 println(byte_num) }}然而这样又批改了代码逻辑,那么是否让编译器本人找到转换方法来进行转换呢?这时候只有在办法前加上一个关键字implicit object Scala_Transform { def main(args: Array[String]): Unit = { // int转换成byte的办法 implicit def itbFun(x:Int):Byte = { x.toByte } val int_num:Int = 21 val byte_num:Byte = int_num println(byte_num) }}编译就会主动找到转换的办法,来进行转换,这个就是隐式转换。 ...

March 1, 2021 · 3 min · jiezi

关于scala:六Scala隐式转换和泛型

1.隐式转换1.1 什么是隐式转换?看如下示例 object Scala_Transform { def main(args: Array[String]): Unit = { val byte_num:Byte = 21 val int_num:Int = byte_num println(int_num) }}这个可能失常打印,因为可能编译器可能进行主动转换,但如果代码改货色,由int转换成byte object Scala_Transform { def main(args: Array[String]): Unit = { val int_num:Int = 21 val byte_num:Byte = int_num //这里会出错 println(byte_num) }}出错起因由Int到Byte没有间接的关系,编译器找不到对应的转换方法。那么咱们提供一个 object Scala_Transform { def main(args: Array[String]): Unit = { // int转换成byte的办法 def itbFun(x:Int):Byte = { x.toByte } val int_num:Int = 21 val byte_num:Byte = itbFun(int_num)//这里会出错 println(byte_num) }}然而这样又批改了代码逻辑,那么是否让编译器本人找到转换方法来进行转换呢?这时候只有在办法前加上一个关键字implicit object Scala_Transform { def main(args: Array[String]): Unit = { // int转换成byte的办法 implicit def itbFun(x:Int):Byte = { x.toByte } val int_num:Int = 21 val byte_num:Byte = int_num println(byte_num) }}编译就会主动找到转换的办法,来进行转换,这个就是隐式转换。 ...

February 27, 2021 · 3 min · jiezi

关于scala:四Scala集合

1.Scala 汇合概述Scala有三类汇合:序列Seq、Set、映射Map。Scala中,简直所有的汇合,都提供可变和不可变两个版本。 个别,咱们依据汇合所在的包来辨别是可变汇合还是不可变汇合。 scala.collection.immutable 不可变汇合scala.collection.mutable 可变汇合2.Scala 汇合2.1 数组2.1.1 不可变数组object Scala_Coll { def main(args: Array[String]): Unit = { // Scala 数组 - 不可变 // 1. 创立数组对象 // 形式一 // new Array[String](5) 编译后会生成java的数组代码 val array = new Array[String](5) // 形式二 val array1 = Array(1,2,3,4) // 2. 打印数组 println(array) // 输入后果 [Ljava.lang.Object;@4cdbe50f // 3.数组赋值,Scala下标索引应用小括号 array(0) = "张三" array(1) = "李四" array(2) = "王五" array(3) = "赵六" // 4.采纳update形式批改数组的值 array.update(4,"哈哈") // 5.查看数组 println(array.mkString(",")) // 6.遍历数组- 形式1 for(i<-array){ println(i) } // 7.遍历数组 - 形式2 // array.foreach(i => println(i)) 精简为 array.foreach(println) /////// 数组操作 /////// // 1)增加数组元素,不可变数组增加数组元素后,返回一个新的数组,自身不会产生扭转 // :+ 增加元素到尾部 val arr1 = array :+ 5 // +: 增加元素到首部 val arr2 = arr1.+:(5) // ++ 增加数组 val arr3 = arr1 ++ arr2 }}2.1.2 可变数组import scala.collection.mutable.ArrayBufferobject Scala_Coll { def main(args: Array[String]): Unit = { // 1.申明可变数组:scala.collection.mutable.ArrayBuffer // 形式1 val arr1 = new ArrayBuffer[Int]() // 形式2 val arr2 = ArrayBuffer(1,2,3,4) // 2.减少数据 arr1.append(4,5,6,7) println(arr1.mkString(",")) // 3.批改数据 arr1.update(1,10) println(arr1.mkString(",")) // 4.删除数据 arr1.remove(1,2) //从索引地位1开始删除2个数据 println(arr1.mkString(",")) // 5.查问数据 println(arr1(1)) // 6.遍历汇合 arr1.foreach(println) // 7. ++ 运算符会产生新的汇合数组 val arr3 = arr1 ++ arr2 println(arr3.mkString(",")) // 8. ++= 运算符则更新之前汇合,并不产生新的数组 arr1 ++= arr2 println(arr1.mkString(",")) }}2.1.3 可变数组和不可变数组的相互转换import scala.collection.mutable.ArrayBufferobject Scala_Coll { def main(args: Array[String]): Unit = { val arr1 = Array(1,2,3,4) // 将不可变数组arr1转换为可变数组 val arr2 = arr1.toBuffer // 将可变数组arr2转换为不可变数组 val arr3 = arr2.toArray }}2.2 Seq汇合2.2.1 不可变listobject Scala_Coll { def main(args: Array[String]): Unit = { // 不可变list // 1.申明对象 val list = List(1, 2, 3, 4) // 2.减少元素,返回新的list val list1 = list :+ 1 // 3.遍历list list1.foreach(println) // 4.空集合Nil // 个别用于减少数据 val list2 = 1 :: 2 :: 3 :: 4 :: Nil println(list2.mkString(",")) // 增加汇合 val list3 = 1 :: 2 :: 3 :: list1 :: Nil println(list3.mkString(",")) // 输入后果 1,2,3,List(1, 2, 3, 4, 1) // 咱们须要将list1的元素作为一个一个的个体应用,也就是扁平化操作 val list4 = 1 :: 2 :: 3 :: list1 ::: Nil println(list4.mkString(",")) // 输入后果 1,2,3,1,2,3,4,1 // 5.连贯汇合 val list5 = List.concat(list3, list4) list5.foreach(println) // 6.创立一个指定反复数量的列表 val list6 = List.fill[String](3)("Hello") list6.foreach(println) }}2.2.2 可变listimport scala.collection.mutable.ListBufferobject Scala_Coll { def main(args: Array[String]): Unit = { // 1.可变list var list1 = new ListBuffer[Int] // 2.减少数据 list1.append(1,2,3,4) val list2 = list1 :+ 5 list1+=5 println(list1.mkString(",")) println(list2.mkString(",")) val list3 = list1 ++ list2 println(list3.mkString(",")) // 3.批改数据 list1.update(1,10) println(list1(1)) // 4.删除数据 list1.remove(1,2) println(list1.mkString(",")) // 5.获取数据 println(list1(1)) }}2.2.3 可变list和不可变list的互相转换import scala.collection.mutable.ListBufferobject Scala_Coll { def main(args: Array[String]): Unit = { // 创立一个不可变汇合 var list = List(1,2,3,4) // 将不可变汇合转变为可变汇合 val buffer = list.toBuffer // 将可变汇合buffer转变为不可变汇合 val list1 = buffer.toList }}2.3 Map映射2.3.1 不可变Mapimport scala.collection.mutable.ListBufferobject Scala_Coll { def main(args: Array[String]): Unit = { // 1.创立Map 两种形式 val map1 = Map("a"->"张三","b"->"李四","c"->"王五") val map2 = Map(("a","张三"),("b","李四"),("c","王五")) println(map1) println(map2) // 2.增加数据 val map3 = map1 + ("d" -> "张三丰") println(map3) // 3.删除数据 val map4 = map3 - "d" println(map4) // 4.批改数据 val map5 = map4.updated("b", "黄蓉") println(map5) // 5.遍历 map5.foreach(println) // 6.获取指定key的值 val str = map5.apply("a") println(str) // 7.获取可能存在的key值 val maybeString:Option[String] = map5.get("a") println(maybeString.get) // 如果是从None值获取会产生异样 println(maybeString.getOrElse(-1)) // 如果获取到返回值,获取不到返回默认值 // 更加简洁的用法 val value = map5.getOrElse("d", -1) println(value) }}2.3.2 可变Mapimport scala.collection.mutableobject Scala_Coll { def main(args: Array[String]): Unit = { // 申明可变Map val map1 = mutable.Map("a" -> "郭靖", "b" -> "黄蓉") val map2 = mutable.Map(("a","杨过"),("b","小龙女")) // 增加数据 map1.put("c","郭襄") val map3 = map1 + ("d" -> "郭芙") map1 += ("d"->"郭芙") // 批改数据 map1.update("d","郭破虏") map1("d") = "郭芙" // 删除数据 map1.remove("d") }}2.4 元组object Scala_Coll { def main(args: Array[String]): Unit = { // 元组能够看成是包容元素的容器,最多能够包容22个元素 // 申明一个元组 val tuple = (1, "a", "张三丰", 18) // 元组中的数据能够通过数据的程序来拜访 println(tuple._1) println(tuple._2) println(tuple._3) println(tuple._4) // 元组遍历 val iterator = tuple.productIterator while (iterator.hasNext){ println(iterator.next()) } // 对偶元组:只有两个元素,也能够叫键值对 val map = Map(("a", "张三丰"), ("b", "张翠山")) //这种申明形式,外面就是对偶元组 }}

February 18, 2021 · 3 min · jiezi

关于scala:Scala学习之路

(一)Scala概述与根底语法(二)Scala函数式编程(三)Scala面向对象

February 18, 2021 · 1 min · jiezi

关于scala:三Scala面向对象

一.面向对象编程根底1.1 包1)申明包:罕用命名形式 域名反写+项目名称+模块名+程序类型名称2)根本语法:和java相似 package cn.leaf.demo033)Scala在根底语法上进行了扩大,性能更加弱小 package关键字嵌套申明package cn{ package leaf{ package demo03{ object Scala_Object{ def main(args: Array[String]): Unit = { println("demo") } } } }}Scala中包和类的物理门路没有关系子包能够间接拜访父包内容,不须要import导入示例 package cn{ package leaf{ class Test{ def fun(): Unit ={ println("test") } } package demo03{ object Scala_Object{ def main(args: Array[String]): Unit = { // 间接应用父包中的Test类 val t = new Test() t.fun() } } } }}1.2 导入import1)根本语法和Java统一2)Scala同样对import进行扩大 import 能够在任意地位应用object Scala_Object{ def main(args: Array[String]): Unit = { import java.util.ArrayList new ArrayList[String]() }}Scala中import能够在同一行导入多个类import java.util.{List, ArrayList}屏蔽包import java.sql.{ Date=>_, Array=>_}给包起别名import java.util.{Date=>UtilDate}1.3 类Scala中没有static成员存在,然而Scala能够通过某种形式达到应用static成员的目标,这个就是伴生机制。在语法层面上,把static成员和非static成员用不同的表达方式,就是class和object。 ...

February 18, 2021 · 2 min · jiezi

关于scala:二Scala函数式编程

函数式编程Scala也是一种函数式编程语言,其函数也能当成值来应用。Scala提供了轻量级的语法用以定义匿名函数,反对高阶函数,容许嵌套多层函数,并反对柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中罕用的代数类型。 在Scala中,存在办法和函数两个概念,办法和函数在语义上区别很细小。Scala 中的办法跟 Java 的相似,办法是组成类的一部分。scala 中的函数则是一个残缺的对象。Scala中办法和函数在语法上区别不大,只是类中申明的函数咱们叫办法,办法有重载和重写,而函数则没有。 1.一般函数编程1.1 根本语法[修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = { 函数体}示例 object Scala_Fun { def main(args: Array[String]): Unit = { test("hello") } /** * 一般函数示例 * @param str */ private def test(str:String):Unit = { println(str) }}1.2 函数定义object Scala_Fun { def main(args: Array[String]): Unit = { // 无参,无返回值 def fun1(): Unit ={ println("无参且无返回值") } // 无参,有返回值 def fun2(): String ={ // 能够省略return "张三" } // 有参,无返回值 def fun3(str:String): Unit ={ println(str) } // 有参,有返回值 def fun4(str:String): String ={ "hello:"+ str } // 关键字参数 }}1.3 函数参数object Scala_Fun { def main(args: Array[String]): Unit = { // 可变参数 def fun1(names:String*): Unit ={ println(names) } fun1("张三","李四") // 可变参数不能搁置在参数列表的后面,个别放在参数列表的最初 // 如果学过python,会发现传参这里跟python传参很类似 /* 谬误示范 def fun2(names:String*, count:Int): Unit ={ }*/ def fun2(count:Int,names:String*): Int ={ println(names) count } // 参数默认值 def fun3(name:String, age:Int = 18): Unit ={ println(name+ ":" + age) } // 命名传参 fun3(name="张三") } }1.4 函数精简准则object Scala_Fun { def main(args: Array[String]): Unit = { // Scala中函数能够进行精简,所谓是能省则省,当然前提是编译器能够主动推断 def fun1(name:String): String ={ return "姓名:"+name } // 1.当函数有返回值时,能够将函数体中最初一行执行的代码作为返回后果,所以能够省略return关键字 def fun2(name:String): String ={ "fun2:"+name } println(fun2("张三")) // 2.如果编译器能够推断出函数的返回值类型,返回值类型则能够省略 def fun3(name:String)={ "fun3:"+name } println(fun3("张三")) // 3.如果函数体逻辑只有一行代码,则函数体的大括号能够省略 def fun4(name:String) = "fun4:"+name println(fun4("张三")) // 4.如果函数没有参数,调用时候,小括号能够省略 def fun5(): String ={ "fun5" } println(fun5) // 5.如果函数没有提供参数,那申明时,小括号能够省略,调用时,也不能应用小括号 def fun6 = "fun6" println(fun6) // 6.如果函数应用Unit申明没有返回值,那函数体中的return关键字不会起作用。 /* def fun7():Unit={ return "张三" }*/ // 7.函数体中如果应用return关键字,则返回值不能省略 def fun8():String = { "fun8" } // 8.如果函数没有返回值,Unit又不想用,那能够同时省略等号,但保留花括号 def fun9(){ println("张三") } // 9.匿名函数:当只关怀代码逻辑,不关怀函数名时,则函数名和def关键字能够省略 // 匿名函数规定: (参数列表) => {函数逻辑} val fun10 = (name:String)=>println(name) fun10("张三") }}2.高阶函数编程2.1什么是高阶函数和柯里化Currying1)数学概念 ...

February 17, 2021 · 2 min · jiezi

关于scala:一Scala概述与基础语法

一.Scala 概述1.1 什么是ScalaScala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种个性。 Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。 Scala 源代码被编译成 Java 字节码,所以它能够运行于 JVM 之上,并能够调用现有的 Java 类库。 Scala官网 https://www.scala-lang.org/ 1.2 装置1.2.1 装置jdk(1.8以上版本)略 1.2.2 装置Scala在官网上下载,我这里是Ubuntu零碎,抉择版本为scala-2.12.11.tgz装置很简略1)解压文件2)将解压后的目录搁置在指定目录 # 我这里是/usr/local 目录mv scala-2.12.11 /usr/local/3)配置环境变量/etc/profile 追加如下内容 # set scalaexport SCALA_HOME=/usr/local/scala-2.12.11export PATH=${PATH}:${SCALA_HOME}/bin执行source /etc/profile 4)测试下如下显示,示意装置胜利 (base) zhaow@zhaow-610:~$ scalaWelcome to Scala 2.12.11 (Java HotSpot(TM) 64-Bit Server VM, Java 11.0.1).Type in expressions for evaluation. Or try :help.scala> 二.Scala 根本语法2.1 第一个Scala程序 HelloWorld学习编程语言,第一个入门程序,必然是HelloWorld.scala object HelloWorld { def main(args: Array[String]): Unit = { // 打印HelloWorld println("Hello World!") }}而后进行编译 ...

February 17, 2021 · 4 min · jiezi

关于scala:Scala-的几种group集合操作

Scala 的几种group汇合操作scala的汇合中有如下几种group操作 groupBy 按特定条件对汇合元素进行分类grouped 将汇合拆分成指定长度的子集合groupMap 应用办法按特定条件对汇合的元素进行分类并解决每个元素groupMapReduce 应用办法按特定条件对汇合中的元素进行分类,别离进行解决,最初将它们reduce这些办法在scala.collection.IterableOps中定义 groupBydef groupBy[K](f: (A) => K): immutable.Map[K, C]返回immutable Map,每个Map由一个键和一个原始类型的值的汇合组成 为了在生成的Map中解决这个值的汇合,Scala提供了mapValues办法 def mapValues[W](f: (V) => W): Map[K, W]这个groupBy / mapValues组合对于解决从分组生成的Map的值十分不便 然而从Scala 2.13开始,办法mapValues不再可用 // Example: groupBycase class Pet(species: String, name: String, age: Int) val pets = List( Pet("cat", "sassy", 2), Pet("cat", "bella", 3), Pet("dog", "poppy", 3), Pet("dog", "bodie", 4), Pet("dog", "poppy", 2), Pet("bird", "coco", 2), Pet("bird", "kiwi", 1))pets.groupBy(_.species)// res5: scala.collection.immutable.Map[String,List[Pet]] = HashMap(// bird -> List(Pet(bird,coco,2), Pet(bird,kiwi,1)), // dog -> List(Pet(dog,poppy,3), Pet(dog,bodie,4), Pet(dog,poppy,2)), // cat -> List(Pet(cat,sassy,2), Pet(cat,bella,3)))groupBy / mapValues组合 ...

December 20, 2020 · 2 min · jiezi

Scalawithcats中文翻译一Type-class与Implicit

前言最近在学习Cats,发现Scala-with-cats这本书写的不错,所以有想法将其翻译成中文,另外也可以在翻译的过程中加深理解,另外我会对每部分内容建议需要了解的程度,帮助大家更好的学习整体内容(有部分内容理解起来比较晦涩且不常用,了解即可),同时我也将相关的练习代码放到github上了,大家可下载参考:scala-with-cats,有翻译不准确的地方,也希望大家能指正????。 本篇内容主要为Type class与Implicit,这应该算是学习Cats需要了解的最基础的内容。 学习程度:需要完全掌握1.1 剖析Type classType class模式主要由3个模块组成: Type class 本身Type class InstancesType class interface1.1.1 Type ClassType class 可以看成一个接口或者 API,用于定义我们想要实现功能。在 Cats 中,Type class相当于至少带有一个类型参数的 trait。比如以下定义代表将一个值转换为Json的行为: // Define a very simple JSON AST 声明一些简单的JSON ASTsealed trait Jsonfinal case class JsObject(get: Map[String, Json]) extends Json final case class JsString(get: String) extends Jsonfinal case class JsNumber(get: Double) extends Jsoncase object JsNull extends Json// The "serialize to JSON" behaviour is encoded in this trait 序列话JSON方法定义在这个Trait里trait JsonWriter[A] { def write(value: A): Json}这个例子中 JsonWriter 就是我们定义的一个 Type class,上述代码中还包含Json类型相关的代码。 ...

June 21, 2020 · 3 min · jiezi

scala学习隐式转换与隐式参数

隐式转换和隐式参数Scala总共有三个地方会使用隐式定义: 转换到一个预期的类型对某个(成员)选择接收端(字段、方法调用等)的转换隐式参数隐式规则标记规则:只有标记为implicit的定义才可用。可标记任何变量、函数、对象作用域规则:被插入的隐式转换必须是当前作用域的单个标识符,或者跟隐式转换的源类型或目标类型有关联每次一个规则:每次只能有一个隐式定义被插入比如编译器绝不会将x+y重写为convert2(convert1(x))+y显示优先规则:只要代码按编写的样子能通过类型检查,就不尝试隐式定义隐式转到到一个预期的类型写过HBase的时候,都知道要写大量的Bytes.toBytes()吧,那么使用隐式转换吧。 object HBasePref { implicit def Str2Bytes(value: Any): Array[Byte] = value match { case str: String => Bytes.toBytes(str) case long: Long => Bytes.toBytes(long) case double:Double => Bytes.toBytes(double) } implicit def str2HBaseTableName(str: String): TableName = TableName.valueOf(str)}与新类型互相操作你期望能够运行1 + new Rational(1,2)这个代码,但int类型显然没有这个方法。用隐式转换吧 implicit def intToRational(x:Int) = new Rational(1,1)模拟新的语法还记得Map初始化的->标识符吗?这么骚的操作也是隐式转换干的 隐式类如果你经常要构造某个类,那么隐式的骚操作就可以这么干。 case class Rectangle(width,height)implicit class RectangleMaker(width:Int) { def x(height:Int) = Rectangle(width,height)}val myRectangle = 3 x 4隐式参数class PreferredPromt(val preference:String)object JoesPrefs { implicit val promt = new PreferredPrompt("Yes master>")}object Greeter { def greet(name:String)(implicit prompt:PreferredPromt) = { println("Welcome," + name) println(prompt.preference) }}import JoesPrefs._Greeter.greet("ljk")

November 5, 2019 · 1 min · jiezi

Spark框架Win10系统下搭建Scala开发环境

一、Scala环境基础Scala对Java相关的类,接口进行了包装,所以依赖Jvm环境。 Jdk 1.8 scala 依赖scala 2.11 安装版本idea 2017.3 开发工具二、配置Scala解压版1)注意路径无空格和中文 2)配置环境变量 添加到path目录 %SCALA_HOME%\bin3)检测是否安装 配置成功,没错就是这么简单。 三、配置Idea开发1)插件安装,就是点点点 2)新建两个maven项目在scala-base-hello 的 main 目录下创建scala文件夹,如下标记。 3)添加scala框架 4)创建scala代码文件 5)一起见证下hello-scala 这代码是不是看起来有点四不像? 四、写在结尾都说万事开头难,现在开了一个完美的头了,剩下的必须都是简单的。

November 2, 2019 · 1 min · jiezi

KafkaProducer源码分析

Kafka常用术语Broker:Kafka的服务端即Kafka实例,Kafka集群由一个或多个Broker组成,主要负责接收和处理客户端的请求 Topic:主题,Kafka承载消息的逻辑容器,每条发布到Kafka的消息都有对应的逻辑容器,工作中多用于区分业务 Partition:分区,是物理概念,代表有序不变的消息序列,每个Topic由一个或多个Partion组成 Replica:副本,Kafka中同一条消息拷贝到多个地方做数据冗余,这些地方就是副本,副本分为Leader和Follower,角色不同作用不同,副本是对Partition而言的,每个分区可配置多个副本来实现高可用 Record:消息,Kafka处理的对象 Offset:消息位移,分区中每条消息的位置信息,是单调递增且不变的值 Producer:生产者,向主题发送新消息的应用程序 Consumer:消费者,从主题订阅新消息的应用程序 Consumer Offset:消费者位移,记录消费者的消费进度,每个消费者都有自己的消费者位移 Consumer Group:消费者组,多个消费者组成一个消费者组,同时消费多个分区来实现高可用(组内消费者的个数不能多于分区个数以免浪费资源) Reblance:重平衡,消费组内消费者实例数量变更后,其他消费者实例自动重新分配订阅主题分区的过程 下面用一张图展示上面提到的部分概念(用PPT画的图,太费劲了,画了老半天,有好用的画图工具欢迎推荐) 消息生产流程先来个KafkaProducer的小demo public static void main(String[] args) throws ExecutionException, InterruptedException { if (args.length != 2) { throw new IllegalArgumentException("usage: com.ding.KafkaProducerDemo bootstrap-servers topic-name"); } Properties props = new Properties(); // kafka服务器ip和端口,多个用逗号分割 props.put("bootstrap.servers", args[0]); // 确认信号配置 // ack=0 代表producer端不需要等待确认信号,可用性最低 // ack=1 等待至少一个leader成功把消息写到log中,不保证follower写入成功,如果leader宕机同时follower没有把数据写入成功 // 消息丢失 // ack=all leader需要等待所有follower成功备份,可用性最高 props.put("ack", "all"); // 重试次数 props.put("retries", 0); // 批处理消息的大小,批处理可以增加吞吐量 props.put("batch.size", 16384); // 延迟发送消息的时间 props.put("linger.ms", 1); // 用来换出数据的内存大小 props.put("buffer.memory", 33554432); // key 序列化方式 props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); // value 序列化方式 props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); // 创建KafkaProducer对象,创建时会启动Sender线程 Producer<String, String> producer = new KafkaProducer<>(props); for (int i = 0; i < 100; i++) { // 往RecordAccumulator中写消息 Future<RecordMetadata> result = producer.send(new ProducerRecord<>(args[1], Integer.toString(i), Integer.toString(i))); RecordMetadata rm = result.get(); System.out.println("topic: " + rm.topic() + ", partition: " + rm.partition() + ", offset: " + rm.offset()); } producer.close(); }实例化KafkaProducer构造方法主要是根据配置文件进行一些实例化操作 ...

October 15, 2019 · 4 min · jiezi

Scala-Type-Parameters-1

类型参数表现形式:在名称后面以方括号表示, Array[T]何处使用 class 中,用于定义变量、入参、返回值 class Pair[T, S](val first: T, val second: S)// scala 可自动推断具体的类型val p = new Pair(42, "String") // Pair[Int, String]函数、方法 def getMiddle[T](a: Array[T]) = a(a.length / 2)类型边界 上边界 T <: UpperBound // 比较大小class Pair[T](val first: T, val second: T) { def smaller = if (first.compareTo(second) < 0) first else second }无法确定 first 是否存在 compareTo 方法,所以必须添加约束,fist 必须是 Comparable 的子类型,即需要添加上边界class Pair[T <: Comparable[T]](val first: T, val second: T) { def smaller = if (first.compareTo(second) < 0) first else second}下边界 T >: LowerBound ...

October 9, 2019 · 2 min · jiezi

Scala-XML

XML直接在代码中使用 XML 字面量 val doc: Elem = <html><head><title>Test</title></head><body>test</body></html>val items: NodeBuffer = <li>item1</li><li>item2</li><li>item1</li><li>item2</li>Scala 中的 Node 与 DOM 不同,不包含父节点信息层级 操作 // 类 XPathval list = <dl><dt>Java</dt><dd>Gosling</dd><dt>Scala</dt><dd>Odersky</dd></dl>val languages = list \ "dt"// 修改元素val list = <ul><li>Fred</li><li>Wilma</li></ul>val list2 = list.copy(label = "ol")// 增加子元素list.copy(child = list.child ++ <li>Another item</li>)// 增加属性val image = <img src="hamster.jpg"/>val image2 = image % Attribute(null, "alt", "An image of a hamster", Null)内嵌表达式,在XML中直接写 Scala 代码块 <ul><li>{items(0)}</li><li>{items(1)}</li></ul><ul>{for (i <- items) yield <li>{i}</li>}</ul><img src={makeURL(fileName)}/> // 注意不需要双引号// 非常规类型val js = <script><![CDATA[if (temp < 0) alert("Cold!")]]></script>模式匹配 ...

October 7, 2019 · 1 min · jiezi

Scala-Future

Futurescala.concurrent.Future 异步执行代码块 import java.time._import scala.concurrent._import ExecutionContext.Implicits.global // 全局线程池Future { Thread.sleep(10000) println(s"This is the future at ${LocalTime.now}")}println(s"This is the present at ${LocalTime.now}")监听结果(阻塞) import scala.concurrent.duration._val f = Future { Thread.sleep(10000); 42 }val result = Await.result(f, 10.seconds) //阻塞10sval f = Future { ... }Await.ready(f, 10.seconds)val Some(t): Option[Try[T]] = f.valuet match { case Success(v) => println(s"The answer is $v") case Failure(ex) => println(ex.getMessage)}ready() 到达等待时间无结果时,会抛出异常 TimeoutException任务抛出的异常时,result() 会再次抛出异常, ready() 可获取结果回调 val f = Future { Thread.sleep(10000) if (random() < 0.5) throw new Exception 42}f.onComplete { case Success(v) => println(s"The answer is $v") case Failure(ex) => println(ex.getMessage)}问题:1.回调地狱;2.执行顺序无法预知 ...

October 7, 2019 · 2 min · jiezi

Scala-Collection-Method

接收一元函数 map 转换元素,主要应用于不可变集合 (1 to 10).map(i => i * i)(1 to 10).flatMap(i => (1 to i).map(j => i * j))transform 与 map 相同,不过用于可变集合,直接转换 ArrayBuffer("Peter", "Paul", "Mary").transform(_.toUpperCase)collect 接收偏函数(PartialFunction)作为参数;模式匹配也是一种偏函数 "-3+4".collect { case '+' => 1 ; case '-' => -1 } // Vector(-1, 1)groupBy 按指定函数分组,返回 Map val words = Array("Abc", "ab")val map = words.groupBy(_.substring(0, 1).toUpperCase)// Map(A -> Array(Abc, ab))接收二元函数 reduceLeft 从左向右规约 f(f(f(a, b), c), d) List(1, 7, 2, 9).reduceLeft(_ - _) // ((1 - 7) - 2) - 9 = 1 - 7 - 2 - 9 = -17reduceRight 从右向左规约 f(a, f(b, f(c, d))) ...

October 2, 2019 · 2 min · jiezi

Scala-Operators-File-RegExp

OperatorsThread.`yield`() 反引号除了用于命名标识符,还可以在调用方法时避免冲突(yield 为 Scala 关键字,但也是 Thread 的方法)中缀运算符(infix operators),实际是带两个参数的方法,定义时跟普通方法一样;a to b 实际是 a.to(b)一元运算符(unary operators) +, -, !, ~四个可当做前缀运算符使用,-a 实际是 a.unary_如果可放在参数后,则是后缀运算符 a identifier赋值操作符(assignment operators),a operator= b 等价于 a = a operator b优先性 * / % > + - > : > < > > ! = > & > ^ > | > 非操作符 > 赋值操作符中缀运算符优先于后缀运算符结合性 所有操作符都是左结合的,除了: 以 : 结尾的操作符 1 :: 2 :: Nil 实际是 1 :: (2 :: Nil)右结合的二元操作符实际是第二个操作对象的方法,如 2 :: Nil 是 Nil.::(2)赋值操作符如果 f(a,b,c) 调用时 f 不是函数或方法,则等价于 f.apply(a,b,c) ...

October 1, 2019 · 2 min · jiezi

Scala-Class-etc-2

Higher-Order Functionsdef 定义的是方法,而不是函数函数可作为变量存在,可直接调用,也可作为值传递给其他函数_ 后缀将普通方法变为函数: ceil _ 根据上下文编译器可以自动将方法转换为函数,也可省略 _ 后缀高阶函数,接收函数的函数参数类型推导 匿名函数传递给其他函数或方法时,如果一直到参数类型,则可省略匿名函数的参数类型,可自动推导类型参数只有一个时可省略括号 当参数在右侧只出现一次时,可使用 _ 简写闭包 Closures,特定作用域SAM, single abstract method interface 对应 Java 中的函数式接口 (1.8)可将 Scala 函数传递给 Java,只在函数字面量中起作用柯里化 Currying 将接收两个参数的函数变为接收第一个参数的函数,该函数返回一个消费第二个参数的函数控制抽象 Control Abstractions Scala 只包含少量的流程控制语句,用户可自定义控制语句Pattern Matching and Case Classes可对任何类型进行模式匹配,匹配顺序从上至下模式匹配代替 switch,默认分支为 case _;可避免 switch 语句中因缺少 break 带来的 fall-through 问题模式匹配也是表达式,可将其返回值直接赋值给变量模式守卫 / guards,为匹配设置条件,任何 Boolean 条件都可作为模式守卫;case ... if ... => ...case 关键字后接变量名或对应数据结构中使用变量名,那么匹配项就赋值给该变量,变量名必须以小写字母开头使用 | 分隔同一匹配的多个可选项,此时不可使用变量绑定元素类型匹配,代替 isInstanceOf 和 asInstanceOf,直接进行类型转换 必须为类型指定变量名,否则匹配的是实际的类型对象匹配在运行时发生,而 JVM 泛型会被擦除 不可以匹配具体的 Map 类型(可使用 case Map[_, _],不可使用 case Map[Int, Int])Array 的类型不会被擦除解构 destructuring ...

September 30, 2019 · 2 min · jiezi

一个关于ollie的论文解读论文目的在于知识图谱三元组提取

前言:模型作用为提取三元组,基于英文,目前尝试改为中文。论文题目名称叫《Open Language Learning for Information Extraction》,代码地址:https://github.com/knowitall/... 论文核心:论文核心主要解决2个问题,一个是基于动词结构之外的三元组提取,例如形容词等,二是基于上下文的三元组提取,举例说明。这里论文与reverb和woe两种抽取方式做比较。 在1-3句话中,基于reverb和woe的提取为none,即什么也提取不到。但基于ollie,其可以提取到,也就是解决了reverb和woe的第一个缺点。举例说明一下:例如第一句Saint 赢了超级杯后,就成了美国橄榄球联盟的顶级球员。 这句话里没有动词,所以reverb和woe什么都提取不到。在4-5句中,ollie是基于上下文的抽取,所以reverb和woe的抽取只能抽到地球是宇宙的中心,但无法抽到eraly astronmers,而ollie能够抽到attributedto。举例:在很早以前人们认为地球是宇宙的中心,reverb和woe提取的是地球是宇宙中心,这显然不对。而ollie可以提取到AttributedTo相信;早期的天文学家。以上两点取自论文Introduction。 如何做的:1.扩展关系短语的句法范围,以涵盖更多的关系表达式。2.扩大开放即表示允许额外的上下文信息,如归因和子句的修饰符 具体做法: (1)构造一个引导集

July 3, 2019 · 1 min · jiezi

Scala系列了不起的Martin-Odersky

本文同步自微信公众号:浮世Talk(ID:fausai_talk) 了不起的人总能做出了不起的事,例如Scala之父Martin Odersky。 1980年,正在慕尼黑大学读本科的Martin第一次接触到编译器便为之痴迷,随即买了一台在当时称得上性能强悍的“便携式“电脑Osborne-1,在随后的日子里,Martin与一位大学好友Peter Sollich终日在一起研究如何为编程语言编写编译器。 他们了解到一门新的编程语言Modula-2,发现该编程语言设计精良,于是便萌生出编写一个适用于8位Z80计算机的Modula-2编译器的想法。带着这个想法,Martin与好友Peter经过不懈努力,在Peter用汇编语言编写的第一个编译器上进行了几个版本的改良后,终于设计出性能相当不错的Modula-2编译器。当时,成立于1983年的软件开发公司Borland看上了Modula-2市场,并且购买了Martin与好友研发的Modula-2编译器,Peter也随即加入了Borland公司。由于Martin还有一年的学业没完成,并且还计划着继续读研深造,所以推迟了加入Borland公司的时间。 在苏黎世联邦理工学院读研期间,Martin似乎找到了他人生为之奋斗的方向,他发现自己更喜欢研究类型的工作,于是放弃了加入了Borland的念头,继续留在苏黎世攻读博士学位,而他的导师就是那位凭借着“算法+数据结构=程序”公式而获得图灵奖的Pascal之父,颇负盛名的计算机科学家Niklaus Wirth。 在苏黎世读博期间,Martin一直致力于函数式程序设计领域的研究。后来成为德国卡尔斯鲁厄大学的一名教授,与好友Phil Wadler一起进行编程理论方面的研究。1995年的某一天,Martin从Phil的朋友口中得知在大西洋彼岸的加州,有一门叫Java的新语言正在Alpha版本阶段。在了解了Java的字节码技术、跨平台运行特点、垃圾回收机制等优势之后,Martin与Phil马上意识到这个Java很可能会颠覆自己的研究,于是,他们开始了新的计划。 Martin与Phil提取了函数式编程的一些特点,如:泛型、高阶函数以及模式匹配,将它们与Java结合。经过努力,他们设计出了一门新的编程语言,命名为Pizza,并于1996年公开发布。事实表明,Pizza是非常成功的,它使得JVM平台与函数式编程语言结合变成现实。 Martin的研究引起了Sun公司核心开发团队人员的关注,很快他们就与Martin取得了联系,并一道合作编写了泛型Java(Generic Java ,简称GJ )。而期间Martin还独立为GJ编写了编译器,Sun公司在对比Java原有的编译器与GJ编译器性能后,决定将GJ编译器作为标准的Javac编译器。2004年,SUN公司发布Java 5,代号为Tiger。这个版本在Java的发展历程中具有里程碑意义 ,而其中最为瞩目的功能就是泛型,这是后话。 在经历了Pizza和GJ设计的Martin对如何让编程语言变得更好,自然是有更多自己的想法,不过现实却时常令他十分沮丧,因为Java具有很强的约束性,使得有某些东西不能往他认为的正确的方向发展,他不得不开始考虑是否有必要从零开始,设计出一个比Java更好的编程语言。 大概2000年前后,正在瑞士洛桑联邦理工大学担任教授的Martin有了一个契机,他拥有一个独立研究的环境,可以组建一个小型研究团队。于是,他带领这个团队基于JVM和Java的类库,设计出一门学术范十足的编程语言Funnel 。不过这门语言看上去十分优雅,却没什么实际可用性。但是经过团队的努力将Funnel与GJ的优势融合之后,他们惊讶的看到距离创造出比Java更加高级的语言已经不远了。 是的,一门崭新的多范式编程语言已呼之欲出,它就是后来人们熟知的Scala。 在2002年的第一场雪前后,Scala拥有了自己的名字。Martin带领团队开始着手Scala的设计,并于2003年正式发布,在2006年经过一次大规模重新设计,此后Scala便开始了稳定高速的发展,到2019年6月已经发布了V2.13。虽然Scala在各种榜单的排名上不如Java,但是凭借着其纯粹的面向对象特点以及函数式编程的优势,使得它不仅具备了和Java一样的面向对象组织大型工程项目的能力,而且又能在大数据计算领域大放异彩。 Scala依靠着它强大的功能与简洁优雅的语法正在征服着广大的开发者,在开源项目方面有彪炳史册、震铄中外的Spark、Kafka、akka等,更有Twitter 、Linkedin等公司在极力推广,相信Scala的未来将更加激动人心。 了不起的Martin Odersky创造了了不起的Scala。 - THE END -扩展练习: 如何搭建Scala开发环境?

June 28, 2019 · 1 min · jiezi

Spark源码拜读一

RDD从一个样子转换成另一个状态,代码执行了,啥也没干,到了最后一步一下干了!懒加载是怎么做到的?打开RDD.scala,看最基础的map方法 /** * Return a new RDD by applying a function to all elements of this RDD. */ def map[U: ClassTag](f: T => U): RDD[U] = withScope { val cleanF = sc.clean(f) new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF)) }其中,val cleanF = sc.clean(f)是把函数f发送到各个task上。返回的还是f。map会创建一个MapPartitionsRDD,可以看到f最后还是由iter调用它自己的map方法来执行的,而这里(context, pid, iter) => iter.map(cleanF)整个是一个函数,也就是说,这个RDD的map方法是把自己和函数传进MapPartitionsRDD了,并没有任何执行。进入MapPartitionsRDD.scala,它是一个RDD的实现类,但里面并没有装数据,只有个函数传进来。 /** * An RDD that applies the provided function to every partition of the parent RDD. */private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag]( var prev: RDD[T], f: (TaskContext, Int, Iterator[T]) => Iterator[U], // (TaskContext, partition index, iterator) preservesPartitioning: Boolean = false) extends RDD[U](prev) { override val partitioner = if (preservesPartitioning) firstParent[T].partitioner else None override def getPartitions: Array[Partition] = firstParent[T].partitions override def compute(split: Partition, context: TaskContext): Iterator[U] = f(context, split.index, firstParent[T].iterator(split, context)) override def clearDependencies() { super.clearDependencies() prev = null }}这就是为什么代码都执行了,rdd该转换了,可是数据并没有动。这里也可以看到,无论是map还是mapPartition,都是把一个分区的数据封装成iterator,执行iterator的同名函数,这个map函数是scala的,不是RDD的。 ...

June 27, 2019 · 3 min · jiezi

Spark系列从零学习Scala并发编程

][6] (文章转载自黑马程序员广州中心官方论坛,发布已获得授权)

June 18, 2019 · 1 min · jiezi

DevOps-基于Walle的小型持续集成实战五基于Walle发布Java应用

本章用于讲解如何在walle下构建和运行JavaWeb。主要包含SpringBoot,ScalaAkkaWeb应用,以Java -jar和Docker运行两种方式(Tomcat方式不讲,大家自行研究)新建项目项目中心 > 项目管理 > 新建项目以下是一份配置好的项目表 分组项目参考备注基本配置项目名称dev-我的JavaDemo项目随便填写,名称不要太长(不好看),最好把环境卸载最前,例如dev(开发环境)基本配置环境开发环境提前在环境管理配置好即可基本配置Git Repogit@gitlab.xxx.com:xxx/java-demo.gitGit仓库地址目标集群目标集群192.168.0.122提前配置服务器管理目标集群目标集群部署路径/data/walle-build/java-demo实际运行的环境目标集群目标集群部署仓库/data/walle-run会存放多个版本编译后的项目目标集群目标集群部署仓库版本保留数5可以回滚的版本数配置脚本Java生态下基本脚本大致一致,无细微差别 基本脚本任务配置 - 部署包含文件包含方式 docker-compose.ymltarget/${SERVER_NAME}.jar该方式用于描述从源码包到发布包中,排除/包含的内容。一般java使用target即可 任务配置 - 自定义全局变量# 运行目录JAVA_HOME=/data/walle-javaRUN_ROOT=/data/walle-runSERVER_NAME=java-demoMVN_HOME=/usr/local/maven3PORT=2223【SpringBoot to Docker】任务配置 - 高级任务-Deploy前置任务pwd/usr/local/maven3//bin/mvn -v任务配置 - 高级任务-Deploy后置任务${MVN_HOME}/bin/mvn clean compile package -Dmaven.test.skip=true -DartifactId=${SERVER_NAME}# cp target/${SERVER_NAME}.jar .sed -i 's/${container_port}/'${PORT}'/g' docker-compose.yml sed -i 's/${container_name}/'${SERVER_NAME}'/g' docker-compose.yml 任务配置 - 高级任务-Release前置任务docker-compose -p ${SERVER_NAME} -f ${WEBROOT}/docker-compose.yml down || echo "服务不存在"docker stop ${SERVER_NAME} || echo "服务不存在"docker rm ${SERVER_NAME} || echo "服务不存在"rm -rf ${WEBROOT}任务配置 - 高级任务-Release后置任务docker-compose -p ${SERVER_NAME} up -decho "服务启动完成"项目 - Maven pom.xml配置<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <build> <finalName>${artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.walle.main.DevelopToolApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> </execution> </executions> <configuration> <includeScope>system</includeScope> </configuration> </plugin> </plugins> </build></project>此处配置了finalName=${artifactId},用于可自定义生成的包名称此处使用了org.springframework.boot进行打包,mainClass设置执行的main方法项目 - docker-compose.yml配置version: '2'services: web: # 镜像:版本 image: openjdk:8-jdk container_name: ${container_name} ports: - "${container_port}:${container_port}" volumes: - ./target/${container_name}.jar:/usr/local/${container_name}.jar - /etc/localtime:/etc/localtime command: /bin/bash -c "echo "Asia/Shanghai" > /etc/timezone && java -Dserver.port=${container_port} -jar /usr/local/${container_name}.jar"映射宿主机./target下的文件${container_name}.jar,到/usr/local/${container_name}.jar映射宿主机的时区到容器启动命令设置时区到上海,随后调用启动参数java -jar,此处可以设置更多的启动参数此处的参数传递方式较差(linux变量替换),可以寻求更好的参数传递方式【ScalaAkka to Docker】任务配置 - 高级任务-Deploy前置任务pwd/usr/local/maven3//bin/mvn -v任务配置 - 高级任务-Deploy后置任务${MVN_HOME}/bin/mvn clean scala:compile compile package -Dmaven.test.skip=true -DartifactId=${SERVER_NAME}# cp target/${SERVER_NAME}.jar .sed -i 's/${container_host}/'${HOST}'/g' docker-compose.yml sed -i 's/${container_port}/'${PORT}'/g' docker-compose.yml sed -i 's/${container_name}/'${SERVER_NAME}'/g' docker-compose.yml 任务配置 - 高级任务-Release前置任务docker-compose -p ${SERVER_NAME} -f ${WEBROOT}/docker-compose.yml down || echo "服务不存在"docker stop ${SERVER_NAME} || echo "服务不存在"docker rm ${SERVER_NAME} || echo "服务不存在"rm -rf ${WEBROOT}任务配置 - 高级任务-Release后置任务docker-compose -p ${SERVER_NAME} up -decho "服务启动完成"项目 - Maven pom.xml配置<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <build> <finalName>${artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.walle.main.DevelopToolApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>allinone</shadedClassifierName> <artifactSet> <includes> <include>*:*</include> </includes> </artifactSet> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Main-Class>com.main.Boot</Main-Class> </manifestEntries> </transformer> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> </execution> </executions> <configuration> <includeScope>system</includeScope> </configuration> </plugin> </plugins> </build></project>如为SpringBoot混合编译,则单独加上scala编译即可 ...

June 17, 2019 · 3 min · jiezi

二Scala基础知识

Scala基础知识谁适合阅读本教程? 本教程适合想从零开始学习 Scala 编程语言的开发人员,强烈建议你有一定的 JAVA 基础,因为 Scala 从 JAVA 演化而来学习任务1、解释器 2、基础语法 3、函数 4、条件与循环 2.1、Scala解释器2.1.1、 交互模式顾名思义就是在命令行调用scala的基础环境,我们在第一篇演示的命令行输出Hello,World!即是。当然Scala在交互模式下能够做很多的事情。在这里我们只做简单的输出演示。 CTRL+C退出交互模式 2.1.2、脚本模式类似于我们在命令行通过 <font color=#7A67EE>java *.java执行</font>一样,我们通过记事本创建一个文件HelloWorld.scala,存储在指定目录,我存储在了/Users/sunliangliang/Desktop/temp这个目录下,代码如下 object HelloWorld { /* 这是我的第一个Scala项目, * 输出"Hello,Scala!" */ def main(args: Array[String]) { println("Hello, Scala!") }}在命令行执行 scala /Users/sunliangliang/Desktop/temp/HelloWorld.scala,看到如下输出结果 2.2、基础语法2.2.1、基础内容普及区分大小写:大小写敏感,即Scala和scala在程序中含义不同类名:首字母大写,驼峰式方法名:首字母小写,驼峰文件名:文件名要和对象/类名匹配包名:全小写常量名:全大写行结尾: 行结尾的";"可省略空格与缩进:运算符前后保留一个空格如: def main(args: Array[String]): Unit = { print("Hello world") }语法规范基本和java一样,其他可参考java相关规范。 2.2.2、变量与常量1、常量的声明:var 常量名 :数据类型 = 值 scala采用数据类型在后面的方式 var str : String = "Scala"2、变量的声明:val 变量名 : 数据类型 = 值 ,如下图 ...

June 14, 2019 · 3 min · jiezi

大数据系列-Scala的初步认识和语法入门

1. Scala简介Scala是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性Scala运行在Java虚拟机上,并兼容现有的Java程序 (Scala是类Jvm言)Scala源代码被编译成Java字节码,所以它可以运行于JVM之上,并可以调用现有的Java类库Spark和flink等大数据框架都是使用Scala开发的2. Scala的版本2.10.x:(兼容spark2.x↓)2.11.x:(兼容spark2.x↑)因为spark2.x后,spark的是使用scala2.11.8编译的,所以在此我们一般企业开发都会选择一致的版本2.11.83. Scala的安装3.1 windows的安装一路下一步,安装完成之后,自动会把路径加入环境变量直接使用即可 3.2 linux的安装解压,配置环境变量即可使用 4. Scala的REPLREPL:Read Eval Print Loop交互式环境(交互式解释器) jdk9.x也支持REPL(jshell) 5. Scala的第一个程序5.1 编写Scala源代码文件Ops1.scala object Test1{ def main(args:Array[String]):Unit={ println("hello bigdata") } }5.2 编译Scala源代码scalac Ops1.scala5.3 执行class文件scala Test16. Scala与Java的区别都是基于JVM虚拟机运行的 Scala编译之后的文件也是.class,都要转换为字节码,然后运行在JVM虚拟机之上Scala和Java相互调用 在Scala中可以直接调用Java的代码,同时在Java中也可以直接调用Scala的代码Java 8 VS Scala Java 8(lambda)没有出来之前,Java只是面向对象的一门语言,但是Java 8出来以后,Java就是一个面向对象和面向函数的混合语言了。scala与java都支持面向对象和函数式编程(jdk1.8才开始支持)Scala设计的初衷是面向函数FPJava的设计初衷是面向对象OOP7. Scala解释器和IDEAScala的解释器 REPLIDEA eclipseIntelliJ IDEA(推荐使用)8. Repl的解释 res0: Int = 12 在我们输入解释器的每个语句后,它会输出一行信息,类似res0: Int = 12。输出的第一部分是REPL给表达式起的变量名。 9. Scala中的变量的定义 var 变量名称:变量类型 = 变量值 ==在scala中除了定义变量还可以定义不可变的量"常量"== val 变量名称:变量类型 = 变量值 在Scala编程中推荐使用val,要val不能解决问题才使用var 10. ==Scala中的类型推断==var a1:Int = 10 ...

June 6, 2019 · 8 min · jiezi

1Scala-环境搭建

注意事项先装好jdkMac OS$ tar -zxvf ~/dev/doc/scala-2.12.8.tgz -C ~/dev/tools/$ ln -s ~/dev/tools/scala-2.12.8/ ~/dev/tools/scala$ vim ~/.bash_profile export SCALA_HOME=/Users/baozi/dev/tools/scala export PATH=$PATH:$SCALA_HOME/bin$ source ~/.bash_profile$ scala -version$ scala$ :q、:quit

April 27, 2019 · 1 min · jiezi

ScalikeJDBC连接MySQL

ScalikeJDBC是一个Scala的JDBC框架,官网说easy-to-use and very flexible,易用又灵活~ 1、添加依赖 <dependency> <groupId>org.scalikejdbc</groupId> <artifactId>scalikejdbc_2.11</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.197</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency>2、上代码 import scalikejdbc._object MySQLDAO { def main(args: Array[String]): Unit = { // initialize JDBC driver & connection pool Class.forName("org.h2.Driver") ConnectionPool.singleton("jdbc:mysql:///film?characterEncoding=utf8", "root", "root") val id = 1 val name = "复联%" val value = sql"""select * from movie where name LIKE $name ORDER BY id DESC """ println(value) // simple example val lasts: List[Map[String, Any]] = DB.readOnly { implicit session => sql"""select * from movie where name LIKE $name ORDER BY id DESC """.map(_.toMap()).list.apply() } println(lasts) }}3、排错1)版本 ...

April 23, 2019 · 1 min · jiezi

快速看图软件中怎么将dwg格式的图纸文件设置输出保存格式为pdf?

快速看图软件中怎么将dwg格式的图纸文件设置输出保存格式为pdf?由于CAD图纸格式的特殊性,所以我们在进行CAD绘制图纸的时候,一般都会将图纸进行其它的格式的转换操作,那么由于PDF图纸格式的各种优势,所以,在平时的转换工作中我们运用的也比较多,但是怎么将查看预览完的CAD图纸文件直接设置转换为PDF格式保存输出?不用转换其它的操作流程?其实转换的方法也有很多,那么下面小编就带大家快速进行操作一种简单快捷的方法。步骤一:首先需要进行打开的是你们电脑桌面上的易用cad快速看图软件,电脑上面如果没有这款软件的,就可以点击任意浏览器搜狗关键词“易用CAD看图”去到CAD官网上面进行下载安装到桌面上即可。步骤二:将软件完成下载后安装到电脑桌面上准备进行操作使用,打开进入软件的首页面选择中间的打开图纸这个选项然后去到桌面上选择打开图纸文件!步骤三:然后我们点击看图软件上方的操作编辑功能,就可以对图纸进行简单的测量或者是其它的编辑操作应用。步骤四:完成以上步骤点击转pdf这个选项之后点击在弹出来的框中去到桌面上选择一个文件夹,我们直接点设置文件的名称还有存储路径就可以将dwg格式的图纸文件保存在我们想要存储的位置了。快速看图软件中怎么将dwg格式的图纸文件设置输出保存格式为pdf的操作演示就到这里了,希望可以对大家有所帮助哦!

March 29, 2019 · 1 min · jiezi

编程高阶用法--词汇

有追求的开发者总会在开发时遇到变量命名困难或者命名冗长庸俗的时候。阅读代码过程中遇到一些很好的命名,也遇到一些不好的。当初并没有记录下来,之后才开始记录,有的也找不到出处了。以下高频词汇供有追求的开发者参考stale 陈腐的,陈旧的 用于需要被替换、刷新的资源transport 传输器restricted 限制的exclusive 专一的of 用于Enum 反例 com.netflix.eureka.Version#toEnum org.springframework.data.domain.PageRequest#of(int, int) HystrixCommandAspect.HystrixPointcutType#ofan /a 对 用于简单封装/适配 com.netflix.discovery.shared.transport.EurekaHttpResponse#anEurekaHttpResponse(int)prefer org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean#preferIpAddresspeer 同等 常见于相互注册scalar 标量的,分等级的; ScalarCallable reactorstream的背压支持anyListOf org.mockito.ArgumentMatchers#anyListOforg.mockito.ArgumentMatchers#argThat 整个mockito都非常简洁,简直就是一套DSLparallelism 平行数,bingfa使用accelerate 使…加速reiterate 重复的做capable 能干的manually 手工relevant 相关的切题的noop 等待 无操作deduce 推断canonical 规范的Indicators 指示灯 candidateIndicatorsdeferred 延期的candidate 候选的slurper 吞噬 json slurperestablished 确定的encapsulate 封装 delimited 限定的capable 能干的,能胜任的 AbstractAutowireCapableBeanFactoryintened 故意的additional 附加的,额外的stub 存根 占位符 corresponding 相当的相应的eligible 合适的mechanism 机制material 重要的,物质的,实质的indicator 指示器 监控系统extern 外来的,走读生alternative 供选择的outBound 向外的、外出的assets 资产neutral 中立的mute 哑的 mute the treadabnormally 反常的intern 软禁 用于进行cache put 出处 com.netflix.discovery.util.StringCache#internsolely 单独的唯一的mutually 相互的 eternal 永恒的compose 排版者demand 要求 ...

March 20, 2019 · 1 min · jiezi

scala常用操作

scala常用操作版本信息python3.7pyspark2.4.0from pyspark import SQLContext,SparkContext,SparkConfconf = SparkConf()sc = SparkContext(conf=conf)sqlContext = SQLContext(sc)#加载csv文件data = sqlContext.read.format(“csv”).option(“header”,“true”).load(“union_order_user”)#按字段降序排序sorted=data.sort(“created_at”,ascending = False)#展示前100条记录 默认展示20条sorted.show(100)

March 9, 2019 · 1 min · jiezi

scala 输出hello world

查看scala版本scala -versionScala code runner version 2.12.8 – Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.运行scala,进入交互式界面➜ ~ scalaWelcome to Scala 2.12.8 (Java HotSpot(TM) 64-Bit Server VM, Java 9.0.4).Type in expressions for evaluation. Or try :help.//输出hell oworldprintln(“Hello World”)//输出//scala> println(“hello world”)//hello world

March 9, 2019 · 1 min · jiezi

SpringBoot整合Scala构建Web服务

今天我们尝试Spring Boot整合Scala,并决定建立一个非常简单的Spring Boot微服务,使用Scala作为编程语言进行编码构建。创建项目初始化项目mvn archetype:generate -DgroupId=com.edurt.ssi -DartifactId=springboot-scala-integration -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0.0 -DinteractiveMode=false修改pom.xml增加java和scala的支持<project xmlns=“http://maven.apache.org/POM/4.0.0" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edurt.ssi</groupId> <artifactId>springboot-scala-integration</artifactId> <packaging>jar</packaging> <version>1.0.0</version> <name>springboot-scala-integration</name> <description>SpringBoot Scala Integration is a open source springboot, scala integration example.</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!– lookup parent from repository –> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!– dependency config –> <dependency.scala.version>2.12.1</dependency.scala.version> <!– plugin config –> <plugin.maven.scala.version>3.1.3</plugin.maven.scala.version> </properties> <dependencies> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>${dependency.scala.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <sourceDirectory>${project.basedir}/src/main/scala</sourceDirectory> <testSourceDirectory>${project.basedir}/src/test/scala</testSourceDirectory> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>${plugin.maven.scala.version}</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>一个简单的应用类package com.edurt.ssiimport org.springframework.boot.SpringApplicationimport org.springframework.boot.autoconfigure.SpringBootApplication@SpringBootApplicationclass SpringBootScalaIntegrationobject SpringBootScalaIntegration extends App{ SpringApplication.run(classOf[SpringBootScalaIntegration])}添加Rest API接口功能创建一个HelloController Rest API接口,我们只提供一个简单的get请求获取hello,scala输出信息package com.edurt.ssi.controllerimport org.springframework.web.bind.annotation.{GetMapping, RestController}@RestControllerclass HelloController { @GetMapping(value = Array(“hello”)) def hello(): String = { return “hello,scala” }}修改SpringBootScalaIntegration文件增加以下设置扫描路径@ComponentScan(value = Array( “com.edurt.ssi.controller”))添加页面功能修改pom.xml文件增加以下页面依赖<!– mustache –><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mustache</artifactId></dependency>修改SpringBootScalaIntegration文件增加以下设置扫描路径ComponentScan的value字段中"com.edurt.ssi.view"在src/main/resources路径下创建templates文件夹在templates文件夹下创建一个名为hello.mustache的页面文件<h1>Hello, Scala</h1>创建页面转换器HelloViewpackage com.edurt.ssi.viewimport org.springframework.stereotype.Controllerimport org.springframework.web.bind.annotation.GetMapping@Controllerclass HelloView { @GetMapping(value = Array(“hello_view”)) def helloView: String = { return “hello”; }}浏览器访问http://localhost:8080/hello_view即可看到页面内容添加数据持久化功能修改pom.xml文件增加以下依赖(由于测试功能我们使用h2内存数据库)<!– data jpa and db –><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope></dependency>修改SpringBootScalaIntegration文件增加以下设置扫描model路径@EntityScan(value = Array( “com.edurt.ssi.model”))创建User实体package com.edurt.ssi.modelimport javax.persistence.{Entity, GeneratedValue, Id}@Entityclass UserModel { @Id @GeneratedValue var id: Long = 0 var name: String = null}创建UserSupport dao数据库操作工具类package com.edurt.ssi.supportimport com.edurt.ssi.model.UserModelimport org.springframework.data.repository.PagingAndSortingRepositorytrait UserSupport extends PagingAndSortingRepository[UserModel, Long] {}创建UserService服务类package com.edurt.ssi.serviceimport com.edurt.ssi.model.UserModeltrait UserService { /** * save model to db / def save(model: UserModel): UserModel;}创建UserServiceImpl实现类package com.edurt.ssi.serviceimport com.edurt.ssi.model.UserModelimport com.edurt.ssi.support.UserSupportimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.stereotype.Service@Service(value = “userService”)class UserServiceImpl @Autowired() ( val userSupport: UserSupport ) extends UserService { /* * save model to db / override def save(model: UserModel): UserModel = { return this.userSupport.save(model) }}创建用户UserController进行持久化数据package com.edurt.ssi.controllerimport com.edurt.ssi.model.UserModelimport com.edurt.ssi.service.UserServiceimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.web.bind.annotation.{PathVariable, PostMapping, RequestMapping, RestController}@RestController@RequestMapping(value = Array(“user”))class UserController @Autowired()( val userService: UserService ) { @PostMapping(value = Array(“save/{name}”)) def save(@PathVariable name: String): Long = { val userModel = { new UserModel() } userModel.name = name return this.userService.save(userModel).id }}使用控制台窗口执行以下命令保存数据curl -X POST http://localhost:8080/user/save/qianmoQ收到返回结果1表示数据保存成功增加数据读取渲染功能修改UserService增加以下代码/* * get all model /def getAll(page: Pageable): Page[UserModel]修改UserServiceImpl增加以下代码/* * get all model */override def getAll(page: Pageable): Page[UserModel] = { return this.userSupport.findAll(page)}修改UserController增加以下代码@GetMapping(value = Array(“list”))def get(): Page[UserModel] = this.userService.getAll(PageRequest.of(0, 10))创建UserView文件渲染User数据package com.edurt.ssi.viewimport com.edurt.ssi.service.UserServiceimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.data.domain.PageRequestimport org.springframework.stereotype.Controllerimport org.springframework.ui.Modelimport org.springframework.web.bind.annotation.GetMapping@Controllerclass UserView @Autowired()( private val userService: UserService ) { @GetMapping(value = Array(“user_view”)) def helloView(model: Model): String = { model.addAttribute(“users”, this.userService.getAll(PageRequest.of(0, 10))) return “user” }}创建user.mustache文件渲染数据(自行解析返回数据即可){{users}}浏览器访问http://localhost:8080/user_view即可看到页面内容增加单元功能修改pom.xml文件增加以下依赖<!– test –><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> <exclusion> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope></dependency>创建UserServiceTest文件进行测试UserService功能package com.edurt.ssiimport com.edurt.ssi.service.UserServiceimport org.junit.jupiter.api.Testimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.boot.test.context.SpringBootTestimport org.springframework.data.domain.PageRequest@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)class UserServiceTest @Autowired()( private val userService: UserService) { @Test def get all() { println(">> Assert blog page title, content and status code”) val entity = this.userService.getAll(PageRequest.of(0, 1)) print(entity.getTotalPages) }}源码地址:GitHub ...

March 1, 2019 · 2 min · jiezi

scala 系列20190202

今天看到一篇关于 scala 入门基础的提问点,我呢,就在这里简单做一下释疑,纯粹是为了抛砖引玉,特别期待各位同行的不吝赐教我先来贴一下原帖的提问点:1、一个数字如果是正数,则它的 signum 为1;如果是负数,则 signum 为 -1;如果是0,则 signum 为0.编写一个函数来计算这个值2、一个空的块表达式{} 的值是什么?类型是什么?3、指出在 Scala 中何种情况下赋值语句 x=y=1 是合法的。(提示:给 x 找个合适的类型定义)4、针对下列 Java 循环编写一个 Scala 版 for(int i =10; i >= 0; i–) System.out.println(i);5、编写一个过程 countdown(n: Int),打印从 n 到 0 的数字6、编写一个 for 循环,计算字符串中所有字母的 Unicode 代码的乘积。举例来说,“Hello” 中所有字符的乘积为 9415087488L7、同样是解决前一个练习的问题,但这次不使用循环(提示:在 Scaladoc 中查看 StringOps)8、编写一个函数 product(s: String),计算前面练习中提到的乘积9、把前一个练习中的函数改成递归函数10、编写函数计算 x^n,其中 n 是整数,使用如下的递归定义:x^n = y^2,如果 n 是正偶数的话,这里的 y = x^(n/2);x^n = x*x^(n-1),如果 n 是正奇数的话;x^0 =1;x^n = 1/x^(-n),如果 n 是负数的话;不得使用 return 语句我们一条一条来看一下:这第一题我没大明白什么是 signum,所以这个先放下,留给各位同行大神来解答喽,刚好也给我讲讲哦,哈哈哈首先我们知道,x=y=1 这是肯定不对的,因为它实际上是这样解析的 x=(y=1),而 y=1 是赋值语句,其返回值是 Unit,所以就相当于是将一个 Unit 赋给 x 了,但是文中又提示给 x 找个合适的类型定义,因此我们只需要将 x 给声明为 var 类型即可 var y = 0; var x = y = 1;这个嘛就比较简单了 for( i <- 0 to 10 ) println(i);首先要说明一下什么是过程,它与函数有什么区别?在 scala 中对于不返回值的函数有特殊的表示法,如果函数体包含在花括号当中,但是没有前面的 = 号,那么返回类型就是 Unit,这样的函数就被称为过程(procedure),过程不返回值,我们调用它仅仅是为了它的副作用由于过程不返回任何值,所以我们可以省略 = 号所以知道了这一点后,我们再来实现题中的要求def coutdown(n : Int){ for( i <- (n + 1) until(0,-1)) println(i);}注意这里不要写成 for(i <- 0 to 10),这样并不符合题意这道题也是有一个陷阱的,就是在声明 s 的时候一定要声明为 Long 型,只要知道这一点后,就比较简单了def countUnicodeMutiple(str : String) = { var s : Long = 1; for(i <- str){ s *= i.toInt; println(s); } }然后调用即可后三道题我先放下,公司今天(2019年2月2日 16:39:45)走的都没人了,数我离家最远,属我最后一个离开,哎,我也写不下去了,要收拾收拾回家了(好难受,喜欢公司里的一个女的,但是人家特别讨厌我;不说了,明年见) ...

February 2, 2019 · 1 min · jiezi

Scala <1>

Scala <1>scala 中的返回值在 scala 中,任何表达式、语句都有返回值;而比较特殊的有以下几种情况:块语句 即形如这样的语句:{} 块的值取决于其内最后一个表达式的值,如:{ val r = r * 2; val a = 1 + 3;},那么这个块表达式的返回值就是 int,因为 a 的类型是 int条件表达式语句 在 scala 中 if/else 的表达式是有返回值的,这个值就是跟在 if/else 之后的表达式的值,例如:if ( x > 0 ) 1 else -1,上述表达式的返回值是 1或者-1,同时这个值也是 if/else 的返回值,你可以将这个返回值赋给一个变量打印输出一下 val i = (if ( x > 0 ) 1 else -1),可以看到返回值确实是 int 如图所示:赋值语句表达式 在 scala 中,赋值动作本身的返回值是 Unit 类型的,unit 类型的返回值并不是空,而是它返回的是一个空的值,就相当于java 系列语言中的 null 和 "" 的区别 【注意】,由于赋值语句的返回值是 Unit,因此如果某个块语句是以赋值语句作为最后一条执行语句的话,那么这个块语句的返回值就变成了 Unit;同时由于赋值语句返回值的特殊性,因此你不能像 java 系列语言那样写:x = y = 1 ,这样是错误的,因为 y = 1 的返回值是 Unit,相当于你将一个 Unit 的空值赋值给一个变量,这样做是没有意义的,当然了,如果你非要这样做,那我告诉你这样做也是正确的,并不会报错,只是它没有意义,不信看下图:输入和输出如果要打印一个值,我们用 print 或 println 函数,但是 println 会在打印的内容后自动追加一个换行符,类似于 shell 编程中的 echo sss 和 echo -n sss 的区别(学习知识注意联想,触类旁通),如果要记忆也简单,println 后面带有 ln ,那就是代表换行了另外还有一个带有格式化的输出 printf 函数,就像这样使用:关于输入的内容,我这里不做过多介绍,只给出两个例子,具体请参考官网标准输入 (当前scala版本:2.12.8) ...

January 31, 2019 · 1 min · jiezi