Chapter 17 《Working with Other Collections》

序列


列表
  • 最重要的序列类型是List类,支持在头部快速添加和移除条目,不支持随机访问。快速的头部添加和移除意味模式匹配很顺畅。
数组
    1. 数组中保存了一个序列的元素。并使用从0开始的随机访问。
    1. new Array[Int](5)生成了一个大小为5的列表,其中的每个元素值都为0。使用array(index)的方法来进行随机访问,是apply函数的语法糖。
列表缓冲(list buffer)
  • ListBuffer是一个可变对象,在列表尾部追加元素的时候比较高效,在头部添加和在尾部添加都是常量时间。可以使用+=在尾部追加,使用+=:在头部添加,完成构造之后,可以使用toList方法来得到最终的List
数组缓冲(ArrayBuffer)
  • Array很像,可以额外的从序列头部或者尾部进行操作,所有的Array操作在ArrayBuffer中都可以实现,不过稍微慢一些。随机访问偶尔需要线性时间,需要分配新的数组来保存缓冲的内容。和ListBuffer一样,存在于可变包中。在创建的时候必须给出类型参数。
字符串StringOps
  • 实现了许多序列方法,在Predef中存在从StringStringOps的隐式转换,可以将任何字符串当做序列来处理。

集合和映射

Scala集合类库同时提供过了可变和不可变两个版本的集合和映射。

Map.png

Set.png

SetMap这两个定义出现了多次,当使用Set或者Map的时候,默认的是一个不可变的对象,因为在Predef中定义了MapSet指向的就是不可变包中的伴生对象。如果想要使用可变的版本,需要显示地做一次引入。

集合
    1. 集合中不存在重复元素,使用==来检查任意的两个元素是否相等。seperator=[,/]+,表示分隔符是指其中的一个元素或者这个元素的多次重复。
    1. 常用的集合操作
    // 不可变集合
    set + 5
    set - 3
    set ++ List(5,6)
    set -- List(5,6)
    Set(1,2,4) & Set(1,2,3,4) 求交集
    set.contains(12)
    Set.empty[String],创建一个空的集合
    // 可变集合
    set(1,2,4) += 4
    set(1,2,4) -= 4
    set(1,2,3) ++= List(2,3,4)
    set(1,2,3) --= List(1,23,4)
    set.clear
    
Map
    1. 写值:map("hello") = 1; map("world") = 2
    1. 读取值:map("hello"),如果不存在这个key,就会报错,使用map.get("hello")的话,返回的是Option类型的值。
    常用的操作
    // 不可变集合
    val nums = Map(1 -> 2, 3 -> 4)
    nums + ( 4 -> 5)
    nums - 4
    nums ++ List(( 4 -> 5), (6 -> 7))
    nums -- List(( 4 -> 5), (6 -> 7))
    nums.contains(1)
    nums(1)
    nums.keys
    nums.keySet
    nums.values
    nums.isEmpty
    // 可变集合
    words += (1 -> 3)
    words -= 1
    words ++= List(1-> 3, 4 -> 5)
    words --= List(1, 4)
    

默认的集和映射

    1. mutable.Set的默认实现类是HashSetmutable.Map的默认实现类是HashMap
    1. 对与不可变集合和映射来说,情况稍微复杂一些。immutable.Set()方法返回的类取决与传入的元素个数。对于少于5个元素的集合,会有专门的特定大小的类与之对应:EmptySet,Set1,Set2,Set3,Set4,如果元素个数大于5,则使用HashSet来实现,不可变的映射实现类似,使用的是HashMap。从Set2中移除一个元素可以得到Set1
排序的集合和映射
  • Scala集合类库提供了SortedSetSortedMap特质,分别由TreeSetTreeMap实现。TreeMap排序的是键的顺序。具体顺序由Ordered特质决定,集合或者映射的键的类型必须混入或者能够被隐式地转换为Ordered

可变和不可变集合类之间的选择

    1. 在元素不多的情况下,使用不可变集合通常比可变集合存储得更紧凑。
    1. 为了将不可变集合转到可变集或者逆操作,Scala提供过了一些语法糖。如果发现a += b的操作,a并不存在+=操作时,Scala将试图将其解读为a = a + b。同样的理念适用于任何以=结尾的方法。这样的好处是只需引入可变版本的Map就可以覆盖实现,避免了大面积上代码的改动。这样的特殊语法不仅适用于集合,也适用于任何值。

初始化集合

  • 创建和初始化一个集合最常见的方式是将初始元素传入所选集合的伴生对象的工厂方法中,只需要将元素放在伴生对象名后的圆括号中即可。Scala编译器会将其转换为伴生对象apply方法的调用。编译器可以通过初始元素的类型来确定集合的类型。但也可以在创建集合时指定跟编译器所选的不同类型。尤其是对可变的集合以及映射。
    val a = mutable.Set(1,2,3)
    a += "string"
    
    是会出错的,a并不会自动转换为Set[Any],这需要在定义的时候明确指出a的类型为Any。因为可变集合和映射实在原来的集合上做修改,不可变集合是copy了原来的集合进行了修改。
转换成数组或者列表
    1. 直接使用toListtoArray方法,需要对集合元素做拷贝,对于大型集合会比较费时,但一般许多集合本来元素就不多,所以因为拷贝带来的性能开销并不高。
    1. 可变集合和不可变集合之间的转变:使用empty++以及++=操作。
immutable.Set.empty[String] ++ muteSet
mutable.Set.empty[Stting] ++= immuteSet

元组

  • 元组可以用来定义一些简单的数据结构,元组中可以存在不同类型的数据,如果一个类的作用就是存储不同类型的数据,可以使用元组来替代这个类。但如果这个类中的字段存在某种意义的时候最好还是定义为类,还可以利用编译器来进行检查。

你可能感兴趣的:(Chapter 17 《Working with Other Collections》)