VI.Collections

1.Array

  • 一些常用方法:println,  map( _ * 2), filter(_ % 2 == 0),  sum,   reserve
  •  Array是不可变的,可变的Array使用ArrayBuffer,需要先引入scala.collection.mutable包。例如,预先不知道数组长度可以使用ArrayBuffer来构建数组,构建完毕后,调用它的toArray方法,得到不可变的Array供后续使用,以提高性能。向ArrayBuffer的尾部添加或删除元素的效率很高,但是在别的位置插入元素的效率就比较低下了。  +,  ++,  prepend,  trimEnd,  insert

2.List      在List的头部进行操作,比尾部效率要高,这是因为List是由单链表实现,访问第一个元素只需要O(1)的时间,而最后一个元素则需要O(n)。

和Array的区别:

Arrays allow you to hold a sequence of elements and efficiently access an element at an arbitrary position, both to get or update the element, with a zero-based index.

Lists support fast addition and removal of items to the beginning of the list, but theydo not provide fast access to arbitrary indexes because the implementation must iterate through the list linearly.

 

1)Nil对象是一个特殊的List对象,其类型是List[Nothing],可用于任何需要List类型实例的场合。

2)构建List:

  • apply
  • ::操作符是List特有的方法,属于右结合操作符,适合于List这样在头部操作效率较高的数据结构。
  • range方法用于构建一个从开始到结束的一系列数字,包含下边界,但是不包含上边界。 range[Int](1,6,2)   range[Char]('a','c')
  • fill方法则用于用一个初始元素创建指定长度的List,该List的每一个元素值都一样。

3)常用操作

  • isEmpty: Boolean:判断List是否有元素
  • length: Int:获取List的长度
  • head: A:取List的第一个元素
  • tail: List[A]:获得List除了第一个元素之外,剩下的list
  • last: A:获取List的最后一个元素
  • init: List[A]:获取除了最后一个元素之外的list
  • apply(n): A:获取第n个元素
  • drop(n): List[A]:去掉左边n个元素,返回剩下的list,对应的,有dropRight(n)方法
  • take(n): List[A]:获取左边n个元素组成的list,也有对应的takeRight(n)方法
  • dropWhile(p: A => Boolean): List[A]:去掉左边满足条件的元素
  • takeWhile(p: A => Boolean): List[A]:获取左边满足条件的元素
  • contains(elem: Any): Boolean:重载SeqLike的方法,判断List是否包含某元素
  • exists(p: A => Boolean): Boolean:重载IterableLike的方法,判断List中是否包含满足给定条件的元素
  • forall(p: A => Boolean): Boolean:重载IterableLike的方法,判断是否List中所有的元素都满足给定条件
  • filter(p: A => Boolean): List[A]:是TraversableOnce特质提供的方法,挑选复合条件的元素组成新的List
  • mkString:是TraversableOnce特质提供的方法,有多个重载,可方便的将一个序列转换为String
  • splitAt(n: Int): (List[A], List[A]):将List从给定位置分成两个部分,返回一对List。
  • :::[B >: A](prefix: List[B]): List[B]:将给定List中的所有元素添加到本List之前。这个方法是右结合运算。

4)List是不可变的,在头部操作效率比较高。如果你需要频繁的更改元素,而且在尾部的操作比较多,可以使用对应的可变集合,ListBuffer。 在ListBuffer上prepend(+=)和append(+=:)操作都是常数时间O(1)。与ArrayBuffer相似,在构建完毕之后,可以使用toList得到不可变的List。

buffer += 2
buffer.+=:(1) // equals to '1 +=: buffer'

3.Set

不同于List和Array,Set分为可变Set和不可变的两个版本。

  • 不可变Set位于scala.collection.immutable包里,由于Predef里包含了不可变Set的定义,默认情况下,你使用的Set是不可变Set。
  • 要使用可变Set,需要显式引用它所在的包。    
  • 在需要排序的情况下,可以使用SortedSet或TreeSet,由红黑树实现。(一般Set都是以HashSet实现,也就是底层数据结构是哈希表)

 

4.Map

Map与Set类似,按可变性,可分为可变Map和不可变Map,按照内部实现,可分为HashMap和TreeMap。

  • 构建不可变的Map可使用Map对象的apply方法,该方法接受一系列键值对作为参数。操作符->标识一个键值对,(a -> b)等价于(a, b)。
val scores = Map(("Jackie", 90), ("Abby", 93), ("Tim", 87))
val caps = Map("China" -> "Beijing", "France" -> "Paris", "Norway" -> "Oslo")
  • 可变map用scala.collection.mutable.Map,可以通过toMap方法返回一个不可变Map。
val teachers = scala.collection.mutable.Map("Chunni" -> "History")
  • 访问Map元素直接用apply方法。如果指定的键不存在,会抛出异常。  //Scala中,'[]'一般是用于在泛型中指定类型。而'()'用于方法调用。
  • 遍历:
    k <- capitals.keySet
    (k, v) <- capitals
    itr.hasNext    //
    val itr = capitals.keysIterator
  • 需要排序的话,可以使用SortedMap或TreeMap。

5.Tuple

  • Tuple是一个方便的集合,可以容纳不同类型的元素,即把一系列对象用小括号'()'括起来。
  • Tuple最常用的就是可一次返回多个对象,而且,还可以用一个语句将这多个对象赋值给其他变量。
  • Tuple是静态类型的,其类型由编译器通过类型推导(type inference)得知。
  • 使用Tuple里的元素,只需用_i按位置获取,比如a._1。  Tuple的位置从1开始,而不是像数组或其他集合那样,从0开始。

 

VII.

包和引用

  • 嵌套的包,可以访问外部的类型,他们在同一范围。但是外部包的类却不能直接访问被嵌套的包里的代码,因为包将内部的代码与外部隔离开来了。
  • 绝对路径可能会被误解为相对路径时,可以在路径前加上_root_
  • 常常有一些公用的方法和静态值或者枚举等内容,并不严格属于项目的类型系统,在Scala中,包级对象可解决这个问题。以'package object'来定义。包级对象文件名是package.scala。
  • 包的引用: import语句可以出现在代码的任何地方,而不仅仅是头部;不但可以引用到类的级别,可以引用包本身;一次引用包内多个成员有两种方式,一种是用通配符'_'引用所有成员,一种是在大括号'{}'内列出需要引用的成员;重命名或隐藏成员,语法是一样的,都是用'[原名称]=>[新名称]'的格式,如果新名称是'_',代表隐藏了原来的类型,而并没有赋予它新的名称,因此该类型将不能使用。

访问修饰符

  • Scala中的private限定符,比Java更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。Scala中的protected限定符,只严格允许自身和派生类访问
  • 可以给访问修饰符指定作用范围,用中括号标记,比如private[this],protected[a-pacakge]。private[this]与private有细微的差别,private代表的访问范围是类级别,private[this]是对象级别,只能从同一对象内部访问。