首页 文章 精选 留言 我的

精选列表

搜索[向量化],共10003篇文章
优秀的个人博客,低调大师

向强大的SVG迈进

作者:凹凸曼 - 暖暖 SVG 即 Scalable Vector Graphics 可缩放矢量图形,使用XML格式定义图形。 一、SVG印象 SVG 的应用十分广泛,得益于 SVG 强大的各种特性。 1.1、 矢量 可利用 SVG 矢量的特点,描出深圳地铁的轮廓: 1.2、iconfont SVG 可依据一定的规则,转成 iconfont 使用: 1.3、 foreignObject 利用 SVG 的 foreignObject 标签实现截图功能,原理:foreignObject 内部嵌入 HTML 元素: <svg xmlns="http://www.w3.org/2000/svg"> <foreignObject width="120" height="60"> <p style="font-size:20px;margin:0;">凹凸实验室 欢迎您</p> </foreignObject> </svg> 截图实现流程: 首先声明一个基础的 svg 模版,这个模版需要一些基础的描述信息,最重要的,它要有 <foreignObject></foreignObject> 这对标签; 将要渲染的 DOM 模版模版嵌入 foreignObject 即可; 利用 Blob 构建 svg 对象; 利用 URL.createObjectURL(svg) 取出 URL。 1.4、SVG SMIL 由于微信编辑器不允许嵌入 <style><script><a> 标签,利用SVG SMIL 可进行微信公众号极具创意的图文排版设计,包括动画与交互。 但是也要注意,标签里不允许有id,否则会被过滤或替换掉。 点击 "凹凸实验室" 后,围绕 "凹凸实验室" 中心旋转 360度,点击0.5秒后 出现 https://aotu.io/ ,动画只运行一次。 下图为 GIF循环演示: 代码如下: <svg width="360" height="300" xmlns="http://www.w3.org/2000/svg"> <g> <!-- 点击后 运行transform旋转动画,restart="never"表示只运行一次 --> <animateTransform attributeName="transform" type="rotate" begin="click" dur="0.5s" from="0 100 80" to="360 100 80" fill="freeze" restart="never" /> <g> <text font-family="microsoft yahei" font-size="20" x="50" y="80"> 凹凸实验室 </text> </g> <g style="opacity: 0;"> <!-- 同一个初始位置以及大致的宽高,触发点击事件 --> <text font-family="microsoft yahei" font-size="20" x="50" y="80">https://aotu.io/</text> <!-- 点击后 运行transform移动动画,改变文本的位置 --> <animateTransform attributeName="transform" type="translate" begin="click" dur="0.1s" to="0 40" fill="freeze" restart="never" /> <!-- 点击0.5秒后 运行opacity显示动画 --> <animate attributeName="opacity" begin="click+0.5s" from="0" to="1" dur="0.5s" fill="freeze" restart="never" /> </g> </g> </svg> 以上是鄙人对SVG的大致印象,最近的需求开发再次刷新了我的认知,那就是 SVG实现非比例缩放 以及 小程序不支持SVG标签的处理,下面容我来讲述一番。 二、SVG 实现非比例缩放 我们熟知的 iconfont,可通过改变字体大小缩放,但是这是 比例缩放,那如何实现 SVG 的非比例缩放呢? 如下图所示,如何将 一只兔子 非比例缩放? 划重点:实现非比例缩放主要涉及三个知识点:viewport、viewBox和preserveAspectRatio,viewport 与viewBox 结合可实现缩放的功能,viewBox 与 preserveAspectRatio 结合可实现非比例的功能。 2.1、viewport viewport 表示SVG可见区域的大小。 viewport 就像是我们的显示器屏幕大小,超出区域则隐藏,原点位于左上角,x 轴水平向右,y 轴垂直向下。 通过类似CSS的属性 width、height 指定视图大小: <svg width="400" height="200"></svg> 2.2、viewBox viewBox值有4个数字:x, y, width, height 。 其中 x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度。 原点默认位于左上角,x 轴水平向右,y 轴垂直向下。 <svg width="400" height="200" viewBox="0 0 200 100"></svg> 显示器屏幕的画面,可以特写,可以全景,这就是 viewBox。 viewBox 可以想象成截屏工具选中的那个框框,和 viewport 作用的结果就是 把框框中的截屏内容再次在 显示器 中全屏显示。 (图片来源:SVG 研究之路 (23) - 理解 viewport 與 viewbox) 2.3、preserveAspectRatio 上图的红色框框和蓝色框框,恰好和显示器的比例相同,如果是下图的绿色框框,怎样在显示器屏幕中显示呢? 2.3.1、 定义 preserveAspectRatio 作用的对象是 viewBox,使用方法如下: preserveAspectRatio="[defer] <align> [<meetOrSlice>]" // 例如 preserveAspectRatio="xMidYMid meet" 其中 defer 此时不是重点,暂且忽略,主要了解 align 和 meetOrSlice 的 用法: align:由两个名词组成,分别代表 viewbox 与 viewport 的 x 方向、y方向的对齐方式。 值 含义 xMin viewport 和 viewBox 左边对齐 xMid viewport 和 viewBox x轴中心对齐 xMax viewport 和 viewBox 右边对齐 YMin viewport 和 viewBox 上边缘对齐。注意Y是大写。 YMid viewport 和 viewBox y轴中心点对齐。注意Y是大写。 YMax viewport 和 viewBox 下边缘对齐。注意Y是大写。 meetOrSlice:表示如何维持高宽的比例,有三个值 meet、slice、none。 meet - 默认值,保持纵横比缩放 viewBox 适应 viewport,可能会有余留的空白。 slice - 保持纵横比同时比例小的方向放大填满 viewport,超出的部分被剪裁掉。 none - 扭曲纵横比以充分适应 viewport。 2.3.2、 例子 例子1:preserveAspectRatio="xMidYMid meet" 表示 绿色框框 与 显示器的 x 方向、y方向的 中心点 对齐; 例子2:preserveAspectRatio="xMidYMin slice" 表示 绿色框框 与 显示器的 x 方向 中心点 对齐,Y 方向 上边缘对齐,保持比例放大填满 显示屏 后超出部分隐藏; 例子3:preserveAspectRatio="xMidYMid slice" 表示 绿色框框 与 显示器的 x 方向、y方向的 中心点 对齐,保持比例放大填满显示屏 后超出部分隐藏; 例子4:preserveAspectRatio="none" 不管三七二十一,随意缩放绿色框框,填满 显示屏即可;这就是非比例缩放的答案了。 三、小程序不支持svg标签怎么办 微信小程序官方不支持 SVG 标签的,但是决定曲线救国,相当于自己实现了一个SVG标签:使用小程序内置的 Canvas 渲染器, 在 Cax 中实现 SVG 标准的子集,使用 JSX 或者 HTM(Hyperscript Tagged Markup) 描述 SVG 结构行为表现。 但是今天我想讲讲其他的。 我们知道,小程序虽然不支持 SVG 标签,但是支持 svg 转成 base64 后作为 background-image 的 url,如 background-image: url("data:image/svg+xml.......) 。 但是我这边还有个需求,随时更改 SVG 每个路径的颜色,即 颜色可配置: 来回转 Base64 肯定是比较麻烦的,有没有更好的方式呢? 直接贴答案:对于SVG图形,还有更好的实现方式,就是直接使用SVG XML格式代码,无需进行base64转换。 3.1、URL 编码 直接使用 SVG XML 格式代码,首先要了解 Data URI的格式。 划重点:base64非必选项,不指定的时候,后面的 <data> 将使用 URL编码。 3.1.1、入门 百分号编码(Percent-encoding), 也称作URL编码(URL encoding),是特定上下文的统一资源定位符 (URL)的编码机制。 原理:ASCII 字符 = % + 两位 ASCII 码(十六进制)。 例如,字符 a 对应的 ASCII 码为 0x61,那么 URL 编码后得到 %61 。 3.1.2、URL 编码压缩 前言: Data URI 的格式中的 <data> 完全使用URL 编码也是可以的,如 encodeURIComponent('<svg version="1.1" viewBox= …</svg>')。 但是和转义前原始SVG相比,可读性差了很多,而且占用体积也变大了。 如果深入了解URL 编码的话,<data> 没必要全部编码的。 正文: RFC3986文档规定,URL中只允许包含 未保留字符 以及 所有保留字符。 未保留字符:包含英文字母(a-zA-Z)、数字(0-9)、-_.~ 4个特殊字符。对于未保留字符,不需要百分号编码。 保留字符:具有特殊含义的字符 :/?#[]@ (分隔Url的协议、主机、路径等组件) 和 !$&'()*+,;= (用于在每个组件中起到分隔作用的,如&符号用于分隔查询多个键值对)。 受限字符或不安全字符:直接放在Url中的时候,可能会引起解析程序的歧义,因此这部分需要百分号编码,如%、空格、双引号"、尖号 <>等等。 综上所述,只需要对 受限字符或不安全字符 进行编码即可。 JS 处理比较简单,利用 replace 将 需要编码的字符 替换掉 即可,基本替换 以下的符号 就够用了: svgToUrl (svgData) { encoded = encoded .replace(/<!--(.*)-->/g, '') // 亲测必须去掉注释 .replace(/[\r\n]/g, ' ') // 亲测最好去掉换行 .replace(/"/g, `'`) // 单引号是保留字符,双引号改成单引号减少编码 .replace(/%/g, '%25') .replace(/&/g, '%26') .replace(/#/g, '%23') .replace(/{/g, '%7B') .replace(/}/g, '%7D') .replace(/</g, '%3C') .replace(/>/g, '%3E') return `data:image/svg+xml,${encoded}` } 如果使用在 CSS 中,可利用 SASS版本3.3以上 的 三个API 对 SVG字符串做替换处理。 str_insert(string, insert, index): 从 $string 第 $index 插入字符 $insert; str_index(string, substring): 返回 $substring 在 $string 中第一个位置; str_slice(string, start_at, end_at = nil): 返回从字符 $string 中第 $start_at 开始到 $end_at 结束的一个新字符串。 前人已有总结,可前往 https://github.com/leeenx/sass-svg/blob/master/sass-encodeuri.scss 查看完整代码。 3.2、SVG 压缩 一般从 Sketch 导出 SVG ,冗余代码比较多,有条件的话建议使用 SVGO 压缩SVG的原本体积,比如清除换行、重复空格;删除文档声明;删除注释;删除desc描述等等。 四、总结 SVG强大的地方在于,出其不意,炫酷,与众不同。 无论是微信公众号花式排版,foreignObject 标签实现截图,实现非比例缩放,或者 背景图直接使用 SVG XML 格式代码,还是上文没有提及的路径动画、描边动画、图形裁剪、滤镜等等,都可以玩出新的花样。 SVG 一个属性可成就一篇文章,学习 SVG 可以说是在挑战自己,欢迎加入 SVG 的学习队列。 五、参考内容 · 推荐阅读 三看 SVG Web 动效 URL编码的奥秘 学习了,CSS中内联SVG图片有比Base64更好的形式 超级强大的SVG SMIL animation动画详解 详细教你微信公众号正文页SVG交互开发 SVG <foreignObject>简介与截图等应用 欢迎关注凹凸实验室博客:aotu.io 或者关注凹凸实验室公众号(AOTULabs),不定时推送文章:

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

技术向深,生态向远:鲲鹏昇腾开源技术高校行·华东站回顾

金秋九月,开源之约如期而至。2026年9月12日,鲲鹏昇腾开源技术高校行·华东站在上海练秋湖举行,近200名高校学子齐聚一堂,与来自vLLM、Triton及openEuler、openGauss、openUBMC等开源社区的技术专家面对面,围绕推理引擎、算子编程、智能运维、AI数据底座与算力管理等前沿方向展开深度交流。活动以“主题分享+Workshop”的全天议程,搭建起从底层算力到上层应用、从技术认知到动手实践的桥梁。

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

Linus Torvalds 向“被动语态”宣战

在日前宣布推出Linux 6.12-rc2 的公告中,Linus Torvalds 对内核维护者 commit 信息的英文语法也提出了更多要求。 他希望,内核维护者在描述拉取请求中的变更时能够避免使用被动语态,更多的使用主动语态、命令式语气。 我试图让我的合并 commit 信息具有一定的“凝聚力”,所以我经常编辑拉取请求的语言,以匹配更标准的布局和语言。这不是什么大不了的事,通常只是与 whitespace 有关,这样我们就不会有 15 种不同的缩进模式和项目符号语法。反正我一般都是在阅读文本的时候做的,所以也不会给我带来额外的工作。 但是,当一些维护者使用被动语态时,我会尝试主动重写解释,这确实会增加额外的工作量。 所以我会要求维护者使用主动语态,最好只是命令式。 换一种说法: 如果大家能避免将描述写成“In this pull request, the Xyzzy driver error handling was fixed to avoid a NULL pointer dereference”,我会非常高兴。 可以写成“This fixes a NULL pointer dereference in ..”;或者,如果只是列出要点,则可以直接写成“Fix NULL pointer dereference in ..”。 我知道这不是什么大问题。但上周我碰巧试着重写了几个这样的案例,我觉得简单明了的语言更好。命令语气的“Fix X”就已经很清楚了。 更多详情可查看邮件列表。

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

Stack Overflow 向谷歌 Gemini 开放 API

Stack Overflow 和 Google Cloud 宣布建立战略合作伙伴关系,将通过 Stack Overflow 平台、Google Cloud Console 和 Gemini for Google Cloud 为开发者提供新的 AI 功能。 他们新推出了一个Overflow API,使得 Google 的 Gemini AI 模型能够访问 Stack Overflow 的知识库,为开发人员提供来自 Stack Overflow 的建议、代码和答案。Overflow API 目前正处于开发阶段,预计将在 4 月份举行的 Google Cloud Next 会议上预览,并于 2024 年上半年推出。 这次合作除了可以帮助谷歌改进Gemini 外,对Stack Overflow 而言也有助于其在 AI 浪潮中保持对开发人员的影响力。此前,Stack Overflow 就推出了一项OverflowAI 产品,旨在为其平台添加生成式 AI 功能。借助于谷歌的合作,其 OverflowAI 产品也或将得到增强。 另一方面,Stack Overflow 去年已经经历了多轮裁员。因此 InfoWorld 指出,尽管谷歌是 Overflow API 的启动合作伙伴,但 Stack Overflow 也有意与更多希望利用其知识库和内容培训 LLM 的公司达成合作。共享数据用于模型训练可以成为公司新的收入来源,也可以为公司提供杠杆,确保在开发人员经常使用的平台上提供数据。 谷歌和 Stack Overflow 没有透露具体的合作财务条款。

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

荷兰或将向勒索攻击宣战

据Security affairs消息,荷兰日前公开宣布,绝不容忍可能威胁到国家安全的勒索软件攻击行为,必要时候可以动用情报或者军事的力量进行遏制。 荷兰外交部长Ben Knapen解释说,不法分子日益频繁的蓄意攻击和及勒索软件对关键基础设施、政府办公室的恶意攻击,已经引起了荷兰当局的重视。 同时他补充说,针对一些破坏性大的网络攻击,荷兰的反应可能会随之升级,比如针对某些关键地方的攻击就需要网络防护部门的快速反应,这是一种无关国家外交关系的反应。 Knapen着重强调,将某次勒索软件攻击归于某个具体的间谍比较困难,因为无法界定一个没有明确国籍的攻击者是否执行了某个国家明确的操作指令。因此,想要在法律上将非国家的行为归属于国家通常并不容易。 “近年来,全球勒索软件攻击正在不断增长。2021年6月,荷兰司法和安全部长在参议院的报告中表示,这些勒索攻击威胁已经纳入2021荷兰网络安全评估(CSAN)之中。CSAN 2021其中的一个结论是,一次破坏力巨大的网络攻击将有可能影响国家安全,比如对那些关键基础设施的破坏。很多情况下,国家一直在保护这些和他们有合作的网络犯罪分子。” Knapen在给荷兰议会的信中写道,“我们在法律意义上没有明确的国家归属时应保持一定的原则,在国家法律的范围内调查一个可能发生的违规行为将会更加合适。而有一定的原则也意味着,各国在行使主权是应考虑到其他国家应有的权利。当国家有足够的信息表明,在本国领土范围内损害了第三方的权利时,他们有责任采取相应的行动。倘若不遵守这一义务,那么就违反了国家法公约。” Knaped解释说,日益严重的勒索软件攻击已经严重威胁到国家安全,因此荷兰政府也将使用任何可以使用的资源进行紧急处理。这一过程包括但不限于调查此次网络攻击,确定具体的不法分子,并对其采取相应的行动。 对国家关键基础设施的攻击,将进一步刺激情报机构和国防网络司令部作出反应,毕竟这两个机构都有相应的网络安全能力,可以对攻击行为进行反击,以确保国家关键基础设施的安全,降低网络攻击带来的损失。 Knapen还进一步强调,荷兰政府对于勒索软件攻击的反应不尽相同,一般首先会使用外交或法律手段来应对可能出现的恶意网络攻击事件。 这封信中还写道,“除了上述外交措施以外,内阁应提高荷兰数字体系整体的弹性。同时还要不断提升荷兰的网络安全能力,强化打击网络犯罪行为,对此内阁将在国家网络安全议程(NCSA)中提出各种针对性措施。例如进一步推广、使用更安全的硬盘和软件,开展网络安全意识教育活动,提高网络威胁的检测能力等。司法和安全部长也在最近的国家网络安全议程中汇报这些措施的进展情况。” 好消息是,目前荷兰尚未出现大规模的针对关键基础设施的勒索软件攻击,而是仅针对于民营商业。 值得注意的是,荷兰政府宣布的这些措施与美国、英国等国家提出的内容相似,针对破坏国家安全的勒索软件攻击,他们都表示将会采取一切措施,包括主动的网络攻击行为,以此捍卫国家安全。 鸿蒙官方战略合作共建――HarmonyOS技术社区 【责任编辑:赵宁宁 TEL:(010)68476606】

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

向Java开发者介绍Scala

Scala结合了面向对象编程与函数编程思想,使用一种能够完全兼容Java、可以运行在Java虚拟机上的、简洁的语法。对于函数编程风格的支持,尤其是对于Lambda表达式的支持,能够有助于减少必须要编写的逻辑无关固定代码,也许让它可以更简单的关注要面对的任务本身,而相对的Java中对Lamdba表达式的支持要到预定于2012年发布的JavaSE8才会实现。本文就是对于Scala介绍。 相关厂商内容 Flash Builder 4.5高级版试用版免费高速下载 QClub(北京站)——《云计算与虚拟化在企业架构中的实施》(10月12日 晚7点) 作为第一步,先安装好最新的Scala发布包Typesafe stack,打开命令行窗口,键入“scala”:这会启动REPL(读入-运算 输出 循环)交互式编码环境。然后你就可以写下你的第一行Scala代码: scala> val columbus : Int = 1492columbus: Int = 1492 我们刚刚声明了一个类型为Int的变量,初始值为1492,就像我们在Java里用语句Int columbus = 1492;所做的一样。除了把类型放在变量之后这样一种反向的声明方式之外,Scala在这里所表现出的不同是使用“val”来显性地把变量声明为不可变。如果我们想要修改这个变量: scala> columbus = 1500 <console>:8: error: reassignment to val columbus = 1500 ^ 请注意错误消息精确地指出了错误位于行的哪个位置。再尝试声明这个变量,但这一次用“var”,让其可变更。这样编译器拥有足够的智能来推断出1492是一个整数,你也就不需要指定类型了: scala> var columbus = 1492 columbus: Int = 1492 scala> columbus = 1500 columbus: Int = 1500 接下来,我们来定义一个类: scala> case class Employee( name:String="guest", age:Int=30, company:String = "DevCode" ) defined class Employee 我们定义了一个类,名为Employee,有三个不可变更的字段:name、age和company,各自有自己的缺省值。关键字“case”相当于Java里的switch语句,只不过要更为灵活。它说明该类具有模式匹配的额外机制,以及其他一些特性,包括用来创建实例的工厂方法(不需要使用“new”关键字来构造),同样的也不需要创建缺省的getter方法。与Java中不同的是,变量缺省下的访问控制是public(而不是protected),而Scala为公开变量创建一个getter方法,并命名为变量名。如果你愿意,你也可以把字段定义成可变且/或私有(private)的,只需要在参数之前使用“var”(例如:case class Person(private var name:String))。 我们再来用不同方式创建一些实例,看看其他的特性,像是命名参数和缺省参数(从Scala2.8开始引入): scala> val guest = Employee() guest: Employee = Employee(guest,30,DevCode) scala> val guestAge = guest.age // (age变量的缺省getter方法) guestAge: Int = 300 scala> val anna = Employee("Anna") anna: Employee = Employee(Anna,30,DevCode) scala> val thomas = Employee("Thomas",41) thomas: Employee = Employee(Thomas,41,DevCode) scala> val luke = Employee("Luke", company="LucasArt") luke: Employee = Employee(Luke,30,LucasArt) scala> val yoda = luke.copy("Yoda", age=800) yoda: Employee = Employee(Yoda,800,LucasArt) 不过,下面的写法 scala> val darth = Employee("Darth", "DevCode") <console>:9: error: type mismatch; found : java.lang.String("DevCode") required: Int Error occurred in an application involving default arguments. val darth = Employee("Darth", "DevCode") ^ 是行不通的(可不是因为Darth不是DevCode的雇员!),这是由于构造函数在这个位置需要age作为参数,因为函数参数没有显性地进行命名。 现在我们再来看集合,这才是真正让人兴奋的地方。 有了泛型(Java5以上),Java可以遍历一个——比方说整数型列表,用下面这样的代码: List<Integer> numbers = new arrayList<Integer>(); numbers.add(1); numbers.add(2); numbers.add(3); for(Integer n:numbers) { System.out.println("Number "+n); } 运行的结果是 Number 1 Number 2 Number 3 Scala对于可变集合和不可变集合进行了系统性地区别处理,不过鼓励使用不可变集合,也因此在缺省情况下创建不可变集合。这些集合是通过模拟的方式实现添加、更新和删除操作,在这些操作中,不是修改集合,而是返回新的集合。 与前面的Java代码等价的Scala代码可能像下面这样: scala> val numbers = List(1,2,3) numbers: List[Int] = List(1, 2, 3) scala> for (n <- numbers) println("Number "+n) Number 1 Number 2 Number 3 这里的“for”循环语法结构非常接近于Java的命令式编程风格。在Scala(以及Java虚拟机上其他很多语言如:Groovy、JRuby或JPython)里还有另外一种方式来实现上面的逻辑。这种方式使用一种更加偏向函数编程的风格,引入了Lambda表达式(有时也称为闭包——closure)。简单地说,Lambda表达式就是你可以拿来当作参数传递的函数。这些函数使用参数作为输入(在我们的例子中就是“n”整型变量),返回语句作为函数体的最终语句。他们的形式如下 functionName { input => body } scala> numbers.foreach { n:Int => // 按回车键继续下一行 | println("Number "+n) | } Number 1 Number 2 Number 3 上面的例子中,函数体只有一条语句(println……),返回的是单位(Unit,也就是“空结果”),也就是大致相当于Java中的void,不过有一点不同的是——void是不返回任何结果的。 除了只打印出我们的数值列表以外,应该说我们更想做的是处理和变换这些元素,这时我们需要调用方法来生成结果列表,以便后面接着使用。让我们尝试一些例子: scala> val reversedList = numbers.reverse reversedList: List[Int] = List(3, 2, 1) scala> val numbersLessThan3 = numbers.filter { n => n < 3 } numbersLessThan3: List[Int] = List(1, 2) scala> val oddNumbers = numbers.filterNot { n => n % 2 == 0 } oddNumbers: List[Int] = List(1, 3) scala> val higherNumbers = numbers.map { n => n + 10 } higherNumbers: List[Int] = List(11, 12, 13) 最后的这一个变换“map”非常有用,它对列表的每一个元素应用闭包,结果是一个同样大小的、包含了每个变换后元素的列表。 我们在这里还想介绍最后的一个方法,就是“foldLeft”方法,它把状态从一个元素传播到另一个元素。比如说,要算出一个列表里所有元素的和,你需要累加它们,并在切换元素的时候保存中间的计数: scala> val sumOfNumbers = numbers.foldLeft(0) { (total,element) => | total + element | } sumOfNumbers: Int = 6 作为第一个变量传递给foldLeft的值0是初始值(也就是说在把函数用到第一个列表元素的时候total=0)。(total,element)代表了一个Tuple2,在Scala里这是一个二元组(就像要表示三维空间坐标,经常要用到Tuple3(x,y,z)等等)。注意在合计时,Scala的编程接口实际上提供了一个“sum”方法,这样上一条语句就可以写成: scala> val sumOfNumbers = numbers.sum sumOfNumbers: Int = 6 还有许多其他的类似的集合变换方法,你可以参照scaladoc API。你也可以把这些方法组合起来(例如:numbers.reverse.filter……),让代码更加简洁,不过这样会影响可读性。 最后,{ n => n + 10 }还可以简单地写成(_ + 10),也就是说如果输入参数只是用于你调用的方法,则不需要声明它;在我们的例子里,“n”被称为匿名变量,因为你可以把它用任何形式来代替,比如说“x”或者“number”,而下划线则表示一处需要用你的列表的每个元素来填补的空白。(与“_”的功能类似,Groovy保留了关键字“it”,而Python则使用的是“self”)。 scala> val higherNumbers = numbers.map(_+10) higherNumbers: List[Int] = List(11, 12, 13) 在介绍了对整数的基本处理后,我们可以迈入下一个阶段,看看复杂对象集合的变换,例如使用我们上面所定义的Employee类: scala> val allEmployees = List(luke,anna,guest,yoda,thomas) allEmployees: List[Employee] = List(Employee(Luke,30,LucasArt), Employee(Anna,30,DevCode), Employee(guest,30,DevCode), Employee(Yoda,800,LucasArt), Employee(Thomas,41,DevCode)) 从这个五个元素的列表里,我们可以应用一个条件来过滤出应用匿名方法后返回值为True的雇员,这样就得到了——比方说属于DevCode的雇员: scala> val devcodeEmployees = allEmployees.filter { _.company == "DevCode" } devcodeEmployees: List[Employee] = List(Employee(Anna,30,DevCode), Employee(guest,30,DevCode), Employee(Thomas,41,DevCode)) scala> val oldEmployees = allEmployees.filter(_.age > 100).map(_.name) oldEmployees: List[String] = List(Yoda) 假设我们手头的allEmployees集合是我们使用SQL查询获得的结果集,查询语句可能类似于“SELECT * FROM employees WHERE company = ‘DevCode’ ”。现在我们可以把List[Employee]变换到以company名称作为键、属于该公司的所有员工的列表作为值的Map类型,这样就可以把雇员按company来排序: scala> val sortedEmployees = allEmployees.groupBy(_.company) sortedEmployees: scala.collection.immutable.Map[String,List[Employee]] = Map(DevCode - > List(Employee(Anna,30,DevCode), Employee(guest,30,DevCode), Employee(Thomas,41,DevCode)), LucasArt -> List(Employee(Luke,30,LucasArt), Employee(Yoda,800,LucasArt))) 每一个列表已经作为一个值存入了(键——值)哈希表,为了示范如何进一步处理这些列表,可以设想我们需要计算每个公司的雇员平均年龄。 这具体意味着我们必须要计算每个列表的每个雇员的的“age”字段的和,然后除以该列表中雇员的数量。让我们先计算一下DevCode: scala> devcodeEmployees res4: List[Employee] = List(Employee(Anna,30,DevCode), Employee(guest,30,DevCode), Employee(Thomas,41,DevCode)) scala> val devcodeAges = devcodeEmployees.map(_.age) devcodeAges: List[Int] = List(30, 30, 41) scala> val devcodeAverageAge = devcodeAges.sum / devcodeAges.size devcodeAverageAge: Int = 33 回到我们的Map (key:String ->value:List[Employee]),下面是个更加一般性的例子。我们现在可以归并并计算每个公司的平均年龄,要做的只是写几行代码: scala> val averageAgeByCompany = sortedEmployees.map{ case(key,value)=> | value(0).copy(name="average",age=(value.map(_.age).sum)/value.size)} averageAgeByCompany: scala.collection.immutable.Iterable[Employee] = List(Employee(average,33,DevCode), Employee(average,415,LucasArt)) 这里的“case(key,value)”说明了Scala提供的模式匹配机制是多么强大。请参考Scala的文档来获取更多的信息。 到这里我们的任务就完成了。我们实现的是一个简单的Map-Reduce算法。由于每个公司雇员的归并是完全独立于其他公司,这个算法非常直观地实现了并行计算。 在后面的附录里给出了此算法的等价的实现,分为Java版本和Scala版本。 参考 The typesafe stack. 附录 Map Reduce: Java public class Employee { final String name; final Integer age; final String company; public Employee(String name, Integer age, String company) { this.name = name == null ? "guest" : name; this.age = age == null ? 30 : age; this.company = company == null ? "DevCode" : company; } public String getName() { return name; } public int getAge() { return age; } public String getCompany() { return company; } @Override public String toString() { return "Employee [name=" + name + ", age=" + age + ", company=" + company + "]"; } } class Builder { String name, company; Integer age; Builder(String name) { this.name = name; } Employee build() { return new Employee(name, age, company); } Builder age(Integer age) { this.age = age; return this; } Builder company(String company) { this.company = company; return this; } } import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.google.common.base.Function; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimaps; public class MapReduce { public static final void main(String[] args) { Employee guest = new Builder("Guest").build(); Employee anna = new Builder("Anna").build(); Employee thomas = new Builder("Thomas").age(41).build(); Employee luke = new Builder("Luke").company("LucasArt").build(); Employee yoda = new Builder("Yoda").age(800).company("LucasArt").build(); Collection<Employee> employees = new ArrayList<Employee>(); employees.add(guest); employees.add(anna); employees.add(thomas); employees.add(luke); employees.add(yoda); ImmutableListMultimap<String, Employee> personsGroupByCompany = Multimaps.index(employees, new Function<Employee,String>() { public String apply(Employee person) { return person.getCompany(); } }); ImmutableSet<String> companyNamesFromMap = personsGroupByCompany.keySet(); List<Employee> averageAgeByCompany = new ArrayList<Employee>(); for(String company: companyNamesFromMap) { List<Employee> employeesForThisCompany = personsGroupByCompany.get(company); int sum = 0; for(Employee employee: employeesForThisCompany) { sum+= employee.getAge(); } averageAgeByCompany.add(new Employee("average",sum/employeesForThisCompany.size(),company)); } System.out.println("Result: "+averageAgeByCompany); } } MapReduce.scala: case class Employee(name: String = "guest", age: Int = 30, company: String = "DevCode") object MapReduce { def main(args: Array[String]): Unit = { val guest = Employee() val anna = Employee("Anna") val thomas = Employee("Thomas", 41) val luke = Employee("Luke", company = "LucasArt") val yoda = luke.copy("Yoda", age = 800) val allEmployees = List(luke, anna, guest, yoda, thomas) val sortedEmployees = allEmployees.groupBy(_.company) val averageAgeByCompany = sortedEmployees.map { case (key, value) => value(0).copy(name = "average", age = (value.map(_.age).sum) / value.size) } println("Result: "+averageAgeByCompany) } } 关于作者 Thomas Alexandre是DevCode的高级咨询顾问,专注于Java和Scala软件开发。他热爱技术,热衷于分享知识,永远在寻求方法、采用新的开源软件和标准来实现更加有效的编程。在十四年的Java开发经验之外,过去几年他集中精力在新的编程语言和Web框架上,例如Groovy/Grails和Scala/Lift。Thomas从法国里尔大学获得了计算机科学博士学位,在卡耐基梅隆大学度过了两年的博士后研究生涯,研究方向是安全和电子商务。 查看英文原文:An Introduction to Scala for Java Developers ============================================================================== 本文转自被遗忘的博客园博客,原文链接:http://www.cnblogs.com/rollenholt/articles/2192384.html,如需转载请自行联系原作者

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

数据泄露向“高价值领域”蔓延

2016年又是各行业、各种大小型企业再次饱受数据泄露困扰的一年。事实一再证明,即使相关机构适时发出了预警,在复杂的网络攻击面前,也没有人可以免受攻击。数据泄露正变得越来越普遍,丝毫没有减速的趋势。 安全解决方案提供商Check Point研究发现,当前的数据泄露多数针对高价值数据:社会保障号码、受保护的健康信息、信用卡和借记卡号码、网络钓鱼、分包商,甚至还有电子邮件、密码和其他的用户访问信息。Check Point预计,2017年将会出现以下安全威胁和趋势。 ——针对移动设备的攻击逐渐增长,源于移动设备的数据泄露将成为最重要的企业安全问题。最近有消息称,黑客针对记者手机上的数据发起攻击的事件开始出现,这意味着这些攻击方法已经在全球蔓延,未来我们会看到有组织的犯罪者也会采用这种方法。 ——在明年,预计网络攻击的范围将扩展至工业物联网。信息技术(IT)和操作技术(OT)的融合使环境变得更加脆弱,特别是操作技术或SCADA环境。这些环境通常运行传统系统,补丁不可用,或者更糟的是不使用补丁。制造业作为一个行业,需要将系统和物理安全控制扩展到合理的平台,并在IT和OT环境中实现威胁防护解决方案。 ——关键基础设施极易受到网络攻击。几乎所有的关键基础设施,包括核电站和电信基站,都是在网络攻击威胁出现之前设计的。在2016年年初,由网络攻击蓄意造成的停电事故已经发生。关键基础设施的安全规划人员需要为一切可能性做好规划。 ——对于企业来说,勒索软件将变得和DDoS攻击一样普遍。鉴于勒索软件的存在,企业需要部署多方面的预防策略包括高级沙盒和威胁净化来有效保护网络。他们也需要考虑其他的方法来应对发起勒索软件活动的人,例如与行业同行协调起诉和执法。我们也将看到“合法的”攻击者发动更有针对性的攻击来影响或压制一个组织。 ——随着企业持续在云上储存更多数据,无形中为黑客提供了“后门”,黑客会想办法攻击云提供商的设施,这将影响所有的客户业务。黑客会增加勒索软件的攻击,影响基于云的数据中心。随着越来越多的组织采用云,包括公有云和私有云,这些类型的攻击开始寻找新的方法来攻击新的基础设施。 就移动、云和物联网而言,市场引爆点很久之前就到来了,这些技术是当今ICT行业最重要的组成部分。不幸的是,网络犯罪已经相应地调整了他们的技术。黑客在涉及恶意软件和勒索软件时,正在“跟上技术发展”,每分钟发布新的变种。基于签名的防病毒软件足以屏蔽恶意软件的时代已经过去。依据这些预测,企业和机构应该制订他们的安全计划,力争在新型网络威胁面前能领先一步,并在攻击造成损害之前进行阻止。 本文转自d1net(转载)

资源下载

更多资源
Mario

Mario

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

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册