​ 最近研究了下scala语言,这个语言最强大的就是它强大的函数式编程(Function Programming)能力,记录下最近学习的一些新的和技巧。注意:本系列博客不会从头讲解该语言的语法,而是通过一些例子讲解该语言的一些技巧,如果需要从头学习scala,建议使用该教程快速入门。

1 Map的基础操作

​ Map的初始化和添加元素操作,如果直接用Map来生成一个对象,那么默认生成的一个不可变对象map,因此,clear等对原有对象进行更改的方法都是不可用的。

   /**
* map的基础操作
*/
def basicMapOp(): Unit = {
var m:Map[String,String] = Map("key" -> "value")
//m("key1") = "value2" // 不支持这种用法
//增加一个键值对
m += ("key1" -> "value1")
println(m)
//如果不存在该键,那么选取默认值
var value = m.getOrElse("key2","defaultValue")
println(s"defaultValue:$value") //对原来的值进行更改
m += ("key1" -> "newValue1")
//合并两个集合
m ++= List("key2" -> "value2", "key3" -> "value3")
//合并的时候,如果存在相同的键(key1),那么会被右边的集合给覆盖掉
m ++= Map("key4" -> "value4", "key5" -> "value5", "key1" -> "valueFromNewMap")
println(m.get("key1"))
//删除一个元素
m -= "key1" var hashMap = mutable.HashMap("hello" -> "world")
hashMap += ("one" -> "two")
println("this is a hashmap! we will clear it!")
hashMap.clear() //注意,这里是不支持的,默认使用Map构造的是个Immutable,所以没有clear方法。
//m.clear //判断是否为空
if (hashMap.isEmpty) {
println("map is empty!")
}
else{
println("map is not empty!")
}
}

2 Map生成view和transform解析

​ Map的mapValues方法会生成一个view,该view会和原先的map关联紧密,并且该view是lazy的,也就是说,每次对该view进行操作(如遍历)的时候,该view才会对原先的map进行操作。来看一个例子:

object MapTest {

  val SEPERATOR = "----------------------"
class ObjClass {
def this(mem: String) = {
this()
this.member = mem
} //表示该函数返回类型为该类类型
def getSelf(): this.type = this var member: String = _ override def toString: String = s"$member"
} def main(args: Array[String]): Unit = {
println(SEPERATOR)
basicMapOp()
println(SEPERATOR) val originMap = Map(1 -> new ObjClass("one"))
println(SEPERATOR)
println(s"m = $originMap")
println(SEPERATOR) //返回的是一个view,并且该view和m强相关,后面每次调用m1,都会使得该view的mapValues被调用一次
val mapValueMap = originMap.mapValues { a => a.member = "two"; println("1:" + a.member); a }
println(s"m = $originMap") //m = one
println(s"m1=$mapValueMap") //1: two
mapValueMap.foreach { kv => kv._2.member = "three"; println("2:" + kv._2.member) } // 1:two 2:three
println(s"m1=$mapValueMap") // 1:two,导致view又重新运行一遍
println(SEPERATOR)
//而transform就不会出现mapValues中的view情况, m2每次被调用,不会到导致transform又重新被运行一次。
val transformMap = originMap.transform { (k, v) => v.member = "four"; v }
//added by seancheer: 注意,这里不带.也是可以的
//val m2 = m transform { (k, v) => v.f = "d"; v }
println(s"m=$originMap") //m = four
originMap.foreach { kv => kv._2.member = "five!"}
println(s"m2=$transformMap") // m2 = five, 返回的view是m的映射,因此修改m,m2也会被更新,同时,不会像mapValueMap那样,每调用一次,就运行一次
println(s"m=$originMap") //m = five
println(SEPERATOR)
} }

​ 可以看到,mapValues返回的投影是lazy型的,每次使用一次返回后的mapValueMap,都会导致mapValues后面的方法体运行一次,从而导致originMap中的元素被重新更新为"two",但是,transform方法返回的投影transformMap就没有这种情况。

​ 需要注意的是,这两个方法返回的都是originMap的一个投影(Projection),更新原始的originMap,会导致投影也发生变化。

Scala语言笔记 - 第二篇的更多相关文章

  1. Scala语言笔记 - 第一篇

    目录 Scala语言笔记 - 第一篇 1 基本类型和循环的使用 2 String相关 3 模式匹配相关 4 class相关 5 函数调用相关 Scala语言笔记 - 第一篇 ​ 最近研究了下scala ...

  2. Scala语言笔记 - 第三篇(容器方法篇)

    Scala语言笔记 - 第三篇(容器方法篇) 目录 Scala语言笔记 - 第三篇(容器方法篇) map和flapMap方法: ​ 最近研究了下scala语言,这个语言最强大的就是它强大的函数式编程( ...

  3. 《javascript权威指南》读书笔记——第二篇

    <javascript权威指南>读书笔记——第二篇 金刚 javascript js javascript权威指南 今天是今年的196天,分享今天的读书笔记. 第2章 词法结构 2.1 字 ...

  4. c#开发Mongo笔记第二篇

    写到第二篇不得不说是我之前犯了一个小错误,其实实现子表存储也是很简单的事,先说我想实现什么样的效果吧 就是用户表里有个成绩字段,成绩字段是个子表 其实实现这个功能也很简单,用面向对象的思想很好理解,子 ...

  5. 瘋子C语言笔记(指针篇)

    指针篇 1.基本指针变量 (1)定义 int i,j; int *pointer_1,*pointer_2; pointer_1 = &i; pointer_2 = &j; 等价于 i ...

  6. js学习笔记第二篇

    Js笔记整理 1.StringAPI a)        大小写转换:str.toUpperCase();str.toLowerCase(); b)        获取指定位置字符: Str[i]-- ...

  7. [Python笔记]第二篇:运算符、基本数据类型

    本篇主要内容有:运算符 基本数据类型等 一.运算符 1.算术运算 2.比较运算 3.赋值运算 4.逻辑运算 5.成员运算 6.身份运算 7.位运算 8.运算符优先级 二.基本数据类型 1.整数:int ...

  8. Android学习笔记(第二篇)View中的五大布局

    PS:人不要低估自己的实力,但是也不能高估自己的能力.凡事谦为本... 学习内容: 1.用户界面View中的五大布局... i.首先介绍一下view的概念   view是什么呢?我们已经知道一个Act ...

  9. Node 之 Express 学习笔记 第二篇 Express 4x 骨架详解

    周末,没事就来公司加班继续研究一下Express ,这也许也是单身狗的生活吧. 1.目录结构: bin, 存放启动项目的脚本文件 node_modules, 项目所有依赖的库,以及存放 package ...

随机推荐

  1. 转: inline关键字使用

    1.inline用在函数声明时,还是函数定义时?还是两边都加? 首先,内联函数声明和定义最好在同一个文件中,其它的情况没有实用上的意义. 只要在同一个文件中,声明和定义至少其一加"inlin ...

  2. leecode之Implement strStr()

    KMP算法的实现: #include <stdio.h> #include <string.h> #include <stdlib.h> int strStr(ch ...

  3. 【敏杰开发】Scrum Meeting 博客汇总

    敏杰开发团队 Scrum Meeting 博客汇总 项目名称:[知识路书] 一.Alpha阶段 Scrum meeting 1 2020/04/07 选题 Scrum meeting 2 2020/0 ...

  4. MySQL之数据定义语言(DDL)

    写在前面 本文中 [ 内容 ] 代表啊可选项,即可写可不写. SQL语言的基本功能介绍 SQL是一种结构化查询语言,主要有如下几个功能: 数据定义语言(DDL):全称Data Definition L ...

  5. 透过“锁”事看InnoDB对并发的处理?

    一. 并发场景下的问题 相对于串行处理方式,并发的事务处理可显著提升数据库的事务吞吐量.提高资源利用率.在MySQL实际应用中,根据场景的不同,可以分为以下几类: 读读并发 读写并发 写写并发 在这些 ...

  6. 一、python入门练习题

    题目: 练习1:华氏温度转摄氏温度. 练习2:输入圆的半径计算计算周长和面积. 练习3:输入年份判断是不是闰年. 答案: 练习1: """ 将华氏温度转换为摄氏温度 F ...

  7. Linux进阶之排错

    Permission denied 检查selinux长时间没有响应 防火墙 nginx和httpd可以自检nginx和httpd有日志 /var/log/nginx/ /var/log/httpd/ ...

  8. 11.3 free:查看系统内存信息

    free命令用于显示系统内存状态,具体包括系统物理内存.虚拟内存.共享内存和系统缓存等. free命令的参数选项及说明 -b    以Byte为单位显示内存的使用情况 -m    以MB为单位显示内存 ...

  9. KVO后[obj class]与object_getClass(id obj)的结果竟会不一致?

    说说背景,研究下面的代码时,KVO后[obj class]与object_getClass(id obj)的结果竟会不一致? PersonModel *aPersonModel = [[PersonM ...

  10. Go语言协程并发---管道信号量应用

    package main import ( "fmt" "math" "strconv" "time" ) /* ·10 ...