关于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