集合

13.1 集合的三大类

所有的集合都扩展Iterable特质。集合的三大集合为Seq, Set, Map

Seq是一个有先后次序的值的序列,比如数组或列表。IndexSeq允许我们通过整型下表快速访问任意元素。但是链表不可以。

Set是一组没有先后次序的值。SortedSet中,元素排过序。

Map时一组(键,值)对。SortedMap按键排序

每一个Scala集合特质或类都有一个带有apply方法的伴生对象。

13.2 可变和不可变集合

13.3 序列Sequence

不可变序列:IndexSeq(Vector, Range), List, Stream, Stack, Queue

可变序列:IndexSeq(ArrayBuffer), LinkedList, Stack, Queue, PriorityQueue, DoubleLinkedList

13.4 列表List

Scala中,列表要么是Nil(空表),要么是一个head元素+tail,而tail也是一个列表。

:: 操作符从给定的head和tail创建一个新的list。例如:9 :: List(4,2)  or 9 :: 4 :: 2 :: Nil

在Java或C++中,我们用迭代器遍历链表。在Scala中使用递归或者模式匹配更自然。例如

def sum(lst: List[Int]): Int = if(lst == Nil) 0 else lst.head + sum(lst.tail)

13.5 可变列表

可变的LinkedList和不可变的List相似,只不过值可以修改。一般采用循环遍历的方式访问每个元素。

注意:如果想要把List中的某个节点变成最后一个节点,不能将next引用设为Nil,而应该将它设置为LinkedList.empty。也不要设置为null,否则在遍历时回遇到空指针错误。

13.6 Set

13.7 Stream

13.8 懒视图

13.9 与Java集合的互操作

13.10 线程安全的集合

Scala提供六个特质,将他们混入集合,让集合的操作变成同步。

SynchronizedBuffer, SynchronizedMap, SynchronizedPriorityMap, SynchronizedQueue, SynchronizedSet, SynchronizedStack

但是,并发地修改或遍历集合并不安全,很可能会引发代码中的错误??

更好多方式是使用java.util.concurrent包中的某个类。比如:ConcurrentHashMap或ConcurrentSkipListMap。这些集合比简单的用同步方式执行所有方法更高效。(因为高效的实现。。)

模式匹配和样例类

Scala有一个十分强大的模式匹配机制,可以应用在很多场合:switch语句、类型查询、以及“析构”(获取复杂表达式中的不同部分)。此外,Scala还提供样例类,对模式匹配进行了优化。

14.1 更好的switch

与if类事,match也是一个表示式,而不是语句。match可以接受任何类型,而不仅仅是数字。

14.2 守卫

守卫可以是任何Boolean条件。例如:case _ if Character.isDigit(ch) => ...

14.5 模式中的变量

case ch if Character.isDigit(ch) => ...

14.6 类型模式

当使用类型匹配时,必须给出一个变量名。否则,就会拿对象本身进行匹配。比如: case x: Int => x

注意:匹配发生在运行期,Java虚拟机中泛型的类型信息是被擦掉的。因此不能用类型匹配特定的Map类型  case m: Map[String, Int] => // Wrong

14.7 样例类

样例类是一种特殊的类,他们经过优化以用于模式匹配。

样例类的实例使用(),样例对象不使用圆括号。

样例对象的copy方法创建一个与现有对象值相同的新对象。

14.8 匹配嵌套结构

case Bundlee(_, _, art @ Article(_, _), rest @ _*) => ...

@表示法将嵌套的值绑到变量;_*表示剩下的序列

14.9 密封类

当用样例类作模式匹配时,如果想让编译器确保已经列出了所有可能,需要将样例类的通用超类声明为sealed. 比如:sealed abstract class Amount

14.10  Option类型

标准库中的Option类型样例类表示那种可能存在、也可能不存在的值。

样例子类Some包装了某个值,例如: Some("Fred")。而样例对象None表示没有值。

Option支持泛型。比如:Some("Fred")的类型为Option[String]。

Option可以通过match, getOrElse, for推导式获得值。

14.11 偏函数

被包在花括号内的一组case语句是一个偏函数——一个并非对所有输入值都有定义的函数。

它是PartialFunction[A, B]类的实例。(A是参数类型,B是返回类型)

该类有两个方法:apply方法从匹配到的模式计算函数值,而isDefinedAt方法在输入至少匹配其中一个模式时返回true

例如:val f: PartialFuntion[Char, Int] = {case '+' => 1; case '-'=>-1}

f('-')  // 返回-1

注解

15.1 什么可以被注解

在Scala中,类、方法、字段、局部变量和参数都可以添加注解,和Java一样。

可以添加多个注解。先后次序没有影响

15.2 注解参数

Java注解可以有带名参数。如果参数名为value,可省略名称。如果不带注解,可省略()。

15.3 针对Java特性的注解

Java修饰符:对于那些不是很常用的Java特性,Scala使用注解,而不是修饰符关键字。

@volatile: 将字段标记为易失的,一个易失的字段可以被多个线程同时更新。

@transient: 将字段标记为瞬态,瞬态的字段不会被序列化。

@stricttfp

@native: 标记那些在C或C++代码中实现的方法。

标记接口:Scala用注解@cloneable和@remote而不是Cloneable和java.rmi.Remote标记接口来表示可被克隆和远程的对象。

注意:@serializable已过时,现在需扩展scala.Serializable特质。对于可序列化的类,可以用@SerialVeresionUID注解来指定序列化版本。

受检异常:Java代码中调用Scala的方法,其签名应包含哪些可能被抛出的受检异常。@throw(classOf[IOException])注解表明会抛出IOException异常。

变长参数:@varargs注解可以从Java调用Scala的带有变长参数的方法。

JavaBeans: 加上JavaBean风格的注解,编译器会帮助生成Java风格的函数。

15.4 用于错误和警告的注解

@deprecated注解生成警告信息,有两个可选参数:message和since

@implicitNotFound注解用于在某个隐式参数不存在的时候生成有意义的错误提醒

@unchecked注解用于在匹配不完整时取消警告的提醒

@uncheckedVariance注解会取消和型变相关的错误提醒

类型参数

16.1 泛型类和泛型函数

和Java和C++一样,类和特质可以带有类型参数。带有一个或者多个类型参数的类是泛型

函数和方法也可以带有类型参数。和泛型类一样,需要吧类型参数放在方法名之后。例如:def getMiddle[T](a: Array[T]) = ...

Scala可以从调用该方法使用的实际参数推断出类型。如有必要,也可以制定类型。例如: val f = getMiddle[String] _

16.2 类型变量界定

Scala允许你通过 边界 来限制多态变量。这些边界表达了子类型关系。

上界:T <: Comparable[T]。例如: class Pair[T <: Comparable[T]](val first: T, val second: T)

下届: R >: T。例如:def replaceFirst[R >: T](newFirst: R) = new Pair(newFirst, second)

16.3 视界界定

视界界定,例如:class Pair[T <% Comparable[T]],<%意味着T可以隐式转换成Comparable[T]。(说明:用Ordered特质更好,它在Comparable[T]基础上还提供关系操作符)

16.4 上下文界定和Manifest

视图界定 T<%V 要求必须存在一个T到V的隐式转换。上下文界定的形式为 T:M,其中M是另一个泛型类。它要求必须存在一个类型为M[T]的“隐式值

例如:class Pair[T : Ordering],上述定义必须存在一个类型为Ordering[T]的隐式值,该隐式值可以用在该类的方法中。

实例化一个泛型Array[T],需要一个Manifest[T]对象。如果需要编写一个泛型函数来构造泛型数组的话,需要传入Manifest对象帮忙。由于它是构造函数的隐式参数,可以使用上下文界定。

16.5 类型约束

T =:= U 测试T是否等于U

T <:< U 测试T是否为U的子类型

T <%< U 测试T能否被隐式转换为U

使用这样的约束,需要添加“隐式类型证明参数”。比如:class Pair[T](val first: T, val second: T)(implicit ev: T <:< Comparable[T])

在上例中,类型约束并没有比类型界定 class Pair[T <: Comparable[T]]带来更多好处。但是前者还可以将隐式参数用在方法上。

16.6 型变Variance

在混合OO和多态性时,一个核心问题是:如果T’T一个子类,Container[T’]应该被看做是Container[T]的子类吗?变性(Variance)注解允许你表达类层次结构和多态类型之间的关系。

协变+T: 与T按照同样的方向型变,Student是Person的子类型,Pair[Student]是Pair[Person]的子类型

逆变-T:与协变相反。

不变:Pair[Student]和Pair[Person]之间没有任何关系,尽管Student时Person的子类型。

16.7 协变和逆变

如果一个对象同时消费和产出某值,则类型应该保持不变。这通常使用于可变数据结构。例如:Scala中数组是不支持型变的。

参数位置是逆变点,而返回类型的位置时协变点。不过,函数参数中,型变规则是反过来的。

16.8 对象不能泛型

16.9 类型通配符

有时候,你并不关心是否能够命名一个类型变量,这时可以使用“通配符”取而代之。比如:def count[A](l: List[A]) = l.size。

如果通配符用得不恰当,可能流失原有类型信息。比如:def drop(l: List[_]) = l.tail 返回的是 List[Any]类型

同时,通配符还可以用在类型变量界定中。比如: def makeFriends(p: [_ <: Person])

高级类型

17.1 单例类型

比如object Title,Title.type就是单例类型,Title本身是单例对象。

17.2 类型投影

嵌套类从属于包含它的外部对象。比如:objectA.Member和objectB.Member是不同的类,即使objectA和objectB是同一个类Network的两个对象。

如果不希望有这种约束,两种方法:

1)把Member类直接挪到主类的伴生对象中。

2)如果坚持细粒度,可以用类型投影,比如:Network#Member,意思是“任何Network的Member”

17.3 路径

路径组成部分不能是类

17.4 类型别名

关键字:type

类型别名必须被嵌套在类或对象中。它不能出现在Scala文件的顶层。

17.5 抽象类型

类或特质可以定义一个在子类中被具体话的抽象类型(abstract type)。比如:trait Reader { type Contents; def read(fileName: String): Contents }

Contents可以在子类中定义

抽象类型 vs 类型参数

  • 如果类型是在类被实例化时给出,则使用类型参数
  • 如果类型是在子类中使用,则使用抽象类型

[Scala] 快学Scala A2L2的更多相关文章

  1. [Scala] 快学Scala A3L3

    Actor 通过尽可能避免锁和共享状态,actor使得我们能够容易地设计出正确.没有死锁或争用状况的程序. Scala类库提供了一个actor模型的简单实现.AKKA是更高级的actor类库. 19. ...

  2. [Scala] 快学Scala A1L1

    基础 1.1 声明值和变量 在Scala中,鼓励使用val; 不需要给出值或变量的类型,这个信息可以从初始化表达式推断出来.在必要的时候,可以指定类型. 在Scala中,仅当同一行代码中存在多条语句时 ...

  3. 快学Scala习题解答—第一章 基础

    1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on th ...

  4. 《快学Scala》

    Robert Peng's Blog - https://mr-dai.github.io/ <快学Scala>Intro与第1章 - https://mr-dai.github.io/S ...

  5. 快学Scala 第十九课 (trait的abstract override使用)

    trait的abstract override使用: 当我看到abstract override介绍的时候也是一脸懵逼,因为快学scala,只介绍了因为TimestampLogger中调用的super ...

  6. Scala快学笔记(二)

    一,基本概念 1,映射 Map与HashMap与TreeMap,SotredMap等区别: 1.HashMap键无序,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度 ...

  7. 快学Scala第一部分

    转载: 1.变量声明 val answer = 8 * 5 + 2; //常量 var counter = 0;    //变量 //在必要的时候 ,可以指定类型 val greeting:Strin ...

  8. 快学scala

    scala 1.   scala的由来 scala是一门多范式的编程语言,一种类似java的编程语言[2] ,设计初衷是要集成面向对象编程和函数式编程的各种特性. java和c++的进化速度已经大不如 ...

  9. 快学Scala 第二课 (apply, if表达式,循环,函数的带名参数,可变长参数,异常)

    apply方法是Scala中十分常见的方法,你可以把这种用法当做是()操作符的重载形式. 像以上这样伴生对象的apply方法是Scala中构建对象的常用手法,不再需要使用new. if 条件表达式的值 ...

随机推荐

  1. [转]一种简单的js时间控件

    使用方法: 粘贴代码到文本文档中,文档名称为datetime.js,然后在html文件中引用如下代码即可 <input name="shijian1" id="sh ...

  2. FineReport实现根据点击次数奇偶性排序的方法

    使用FineReport报表软在进行排序的时,很多时候您可能想实现根据点击的次数进行升降序排序,也就是说点击第一次点击标题升序排序,再次点击就降序,以此类推,而不是通过选择升序进行升序排列,选择降序进 ...

  3. 关于安装ruby brew 提示失败

    Error running 'requirements_osx_brew_update_system ruby-1.9.3-p551', showing last 15 lines of /Users ...

  4. 骨骼蒙皮动画算法(Linear Blending Skinning)

    交互式变形是编辑几何模型的重要手段,目前出现了许多实时.直观的交互式变形方法.本文介绍一种利用线性混合蒙皮(Linear Blending Skinning,LBS)技术来实现网格变形的方法,线性混合 ...

  5. 洛谷CON1041 NOIP模拟赛一试

    A T2-power of 2 题目描述 是一个十分特殊的式子. 例如: n=0时 =2 然而,太大了 所以,我们让对10007 取模 输入输出格式 输入格式: n 输出格式:  % 10007 输入 ...

  6. 第21章 java线程(1)-线程初步

    java线程(1)-线程初步 1.并行和并发 并行和并发是即相似又有区别: 并行:指两个或者多个事件在同一时刻点发生. 并发:指两个或多个事件在同一时间段内发生 在操作系统中,并发性是指在一段事件内宏 ...

  7. Path Sum II

    Path Sum II Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals ...

  8. openstack上创建vm实例后,状态为ERROR问题解决

    问题说明:在openstack上创建虚拟机,之前已顺利创建了n个centos6.8镜像的vm现在用ubuntu14.04镜像创建vm,发现vm创建后的状态为ERROR! 1)终端命令行操作vm创建 [ ...

  9. 搭建一套自己实用的.net架构(4)【CodeBuilder-RazorEngine】

    工欲善其事必先利其器,  下面来说说代码生成器. 现在代码生成器品种繁多各式各样, 什么codesmith.T4. 动软也算.那么每款代码生成器都有自己模板解析引擎. 现在比较流行的 NVelocit ...

  10. jQuery美化下拉菜单插件dropkick

    dropkick是一款基于jquery库的美化下拉框下拉菜单的插件,它通过定制HTML插入可使丑陋无聊的<select>下拉列表变得美丽. name属性是唯一一个必需的填写的,不过你也应该 ...