Scala's object-oriented collections support mutable and immutable type hierarchies. Also support functional higher-order operations such as map, filter, and reduce that let you use expression-oriented programming in collections. Higher-order operations are not available with Java Collections library.
1. Scala Collection Hierarchy
  Most collection classes exist in three packages: scala.collection, scala.collection.immutable, and scala.collection.mutable.
  (1) package scala.collection

  All types in scala.collections package are implemented in different ways in the Scala libraries based on whether the implementations are immutable or mutable. To keep these different implementations separate, there are packages called scala.collection.immutable and scala.collection.mutable.

    1) Sequences
    Sequences store a number of different values in a specific order. Sequences branch off into two main categories: indexed sequences and linear sequences.

# by default, Seq creates a List
scala> val x = Seq(,,)
x: Seq[Int] = List(, , )
# by default, IndexedSeq creates a Vector
scala> val x = IndexedSeq(,,)
x: IndexedSeq[Int] = Vector(, , ) 

    2) Sets
    A Scala Set is a collection of unique elements. By default, Set creates an immutable Set.

# colletion.immutable.package is automatically added to the current namespace. The collection.mutable is not.
scala> val x = Set(,,)
x: scala.collection.immutable.Set[Int] = Set(, , )

    3) Map

    Scala Map is a collection of key/value pairs, where all the keys must be unique.

# creating an immutable Map without requiring an import
scala> val map = Map( -> "a", -> "b", -> "c")
map: scala.collection.immutable.Map[Int,String] = Map( -> a, -> b, -> c)

  (2) package scala.collection.immutable

  # immutable Seq

  # immutable Set

  # immutable Map

    1) Immutable Sequence

    If you want an immutable collection that has efficient indexing, your default choice would generally be Vector.

# an immutable IndexedSeq creates a Vector
scala> val x = scala.collection.immutable.IndexedSeq(,,)
x: scala.collection.immutable.IndexedSeq[Int] = Vector(, , )
# an immutable LinearSeq creates a List
scala> val x = scala.collection.immutable.LinearSeq(,,)
x: scala.collection.immutable.LinearSeq[Int] = List(, , )
# an immutable Seq creates a List
scala> val x = scala.collection.immutable.Seq(,,)
x: scala.collection.immutable.Seq[Int] = List(, , )

    A collection in package scala.collection.immutable will never change for everyone after it is created.

    2) Immutable Set

# using an immutable Set
scala> val m = collection.immutable.Set(,,)
m: scala.collection.immutable.Set[Int] = Set(, , )
# an immutable SortedSet creates a TreeSet
scala> val m = collection.immutable.SortedSet(,,)
m: scala.collection.immutable.SortedSet[Int] = TreeSet(, , )
# using an immutable BitSet
scala> val m = collection.immutable.BitSet(,,)
m: scala.collection.immutable.BitSet = BitSet(, , )

    3) Immutable Map

# using an immutable map without requiring an import
scala> val m = Map(->"a",->"b")
m: scala.collection.immutable.Map[Int,String] = Map( -> a, -> b)
# using an immutable Map with the prefix
scala> val m = collection.immutable.Map(->"a",->"b")
m: scala.collection.immutable.Map[Int,String] = Map( -> a, -> b)
# using an immutable.SortedMap
scala> val m = collection.immutable.SortedMap(->"a",->"b")
m: scala.collection.immutable.SortedMap[Int,String] = Map( -> b, -> a)

  (3) package scala.collection.mutable

  By default, Scala always picks immutable collections. To get the mutable default versions, you need to write explicitly collection.mutable.Set or collection.mutable.Iterable.
  Note that a useful convention if you want to use both mutable and immutable versions of collections is to import just the collection.mutable. Then a word like Set without a prefix still refers to an immutable collections, whereas mutable.Set refers to the mutable counterpart.

scala> import scala.collection.mutable
import scala.collection.mutable

  1) mutable sequences

    a) Buffer
    There is no immutable Buffer. Two most significant subtypes of Buffer are ArrayBuffer and ListBuffer.

# creating a Buffer
scala> val buffer = collection.mutable.Buffer(,,)
buffer: scala.collection.mutable.Buffer[Int] = ArrayBuffer(, , )
# a mutable Seq creates as ArrayBuffer
scala> val x = scala.collection.mutable.Seq(,,)
x: scala.collection.mutable.Seq[Int] = ArrayBuffer(, , )
# a mutable LinearSeq creates as MutableList
scala> val x = scala.collection.mutable.LinearSeq(,,)
x: scala.collection.mutable.LinearSeq[Int] = MutableList(, , )
# a mutable IndexedSeq creates an ArrayBuffer
scala> val x = collection.mutable.IndexedSeq(,,)
x: scala.collection.mutable.IndexedSeq[Int] = ArrayBuffer(, , )
# a mutable Set
scala> val m = collection.mutable.Set(,,)
m: scala.collection.mutable.Set[Int] = Set(, , )
# a mutable SortedSet create a TreeSet
scala> val m = scala.collection.mutable.SortedSet(,,)
m: scala.collection.mutable.SortedSet[Int] = TreeSet(, , )
# a mutable BitSet
scala> val m = scala.collection.mutable.BitSet(,,)
m: scala.collection.mutable.BitSet = BitSet(, , )
# a mutable Map
scala> val m = collection.mutable.Map(->"a",->"b")
m: scala.collection.mutable.Map[Int,String] = Map( -> b, -> a)

2. Using Immutable Collection Classes

# List
scala> val x = List(,,,)x: List[Int] = List(, , , )
# filtering through List
scala> x.filter(a => a % ==)
res0: List[Int] = List(, )
scala> x
res1: List[Int] = List(, , , )
# Array
scala> val a = Array(,,)
a: Array[Int] = Array(, , )
scala> a()
res2: Int =
# Map
scala> val m = Map("one"->,"two"->)
m: scala.collection.immutable.Map[String,Int] = Map(one -> , two -> )
scala> m("two")
res3: Int =

  Lazy collections have elements that may not consume memory until they are accessed(e.g., Range)

scala>  to
res7: scala.collection.immutable.Range.Inclusive = Range(, , , , , )

  The nifty(精巧的) thing about Ranges is that the actual elements in the Range are not instantiated until they are accessed.

# Using Range as Lazy Collection
scala> ( to Integer.MAX_VALUE - ).take()
res8: scala.collection.immutable.Range = Range(, , , , )

  Note that immutable collections may contain mutable items.

  (1) Vector

# creating a Vector
scala> val x = IndexedSeq(,,)
x: IndexedSeq[Int] = Vector(, , )
scala> x()
res9: Int =

  You can't modify a vector, so you add elements to an existing vector as you assign the result to a new variable.

scala> val a = Vector(,,)
a: scala.collection.immutable.Vector[Int] = Vector(, , )
scala> val b = a ++ Vector(,)
b: scala.collection.immutable.Vector[Int] = Vector(, , , , )

  Use the updated method to replace one element in a vector while assigning the result to a new variable.

scala> val c = b.updated(,"x")
c: scala.collection.immutable.Vector[Any] = Vector(x, , , , )
scala> val a = Vector(,,,,)
a: scala.collection.immutable.Vector[Int] = Vector(, , , , )
scala> val b = a.take()
b: scala.collection.immutable.Vector[Int] = Vector(, )
scala> val c = a.filter(_ > )
c: scala.collection.immutable.Vector[Int] = Vector(, , )
# declare variable as a var and reassign the result back to the same variable
scala> var a = Vector(,,)
a: scala.collection.immutable.Vector[Int] = Vector(, , )
scala> a = a ++ Vector(,)
a: scala.collection.immutable.Vector[Int] = Vector(, , , , )

  When you create an immutable Vector as a var, it appears you can somehow add new elements to it:

scala> var int = Vector()
int: scala.collection.immutable.Vector[Int] = Vector()
scala> int = int :+ :+
int: scala.collection.immutable.Vector[Int] = Vector(, , )
scala> int.foreach(println)

  What's really happening is that the int variable points to a new collection each time you use the :+. The int variable is actually being reassinged to a new collection during each step.

  (2) List[T]

scala>  ::  ::  :: Nil
res11: List[Int] = List(, , )
# Anything that looks like an operator with a:(colon) as the first character is evaluated right to left.
scala> new ::(, new ::(, new ::(,Nil)))
res12: scala.collection.immutable.::[Int] = List(, , )
# sometimes you need to help type inferencer along
scala> List(,44.5,8d)
res13: List[Double] = List(1.0, 44.5, 8.0)
scala> List[Number](,44.5,8d)
res14: List[Number] = List(, 44.5, 8.0)
# Note that the list referred to by the variable x is unchanged, but a new List is created with a new head and the old tail.You can also merge two lists to form a new list. The operation is O(n).
scala> val x = List(,,)
x: List[Int] = List(, , )
scala> val y = List(,,)
y: List[Int] = List(, , )
scala> x ::: y
res15: List[Int] = List(, , , , , )

3. Getting Functional

scala> List(,,).filter(x => x % == )
res17: List[Int] = List(, )

  If filter returns true, the elements is included in the resulting collection. The resulting collection is the same type of collection that filter was invoked on.

scala> def isOdd(x: Int) = x %  ==
isOdd: (x: Int)Boolean

  Filter works with any collections that contain any type.

scala> "99 red balloons".toList.filter(Character.isDigit)
res20: List[Char] = List(, )

  Another useful method for picking the right elements out of a List is takeWhile.

# 从左往右提取数据,直到条件不满足时停止
scala> "Elwood eat mice".takeWhile(c => c != ' ')
res22: String = Elwood

4. Transformation

  The map method on List (and Seq) transforms each element of a collection based on a function.

scala> List("A","Cat").map(s => s.toLowerCase)
res23: List[String] = List(a, cat)

  If the function passed into map returns a different type, then the resulting collection is a collection of the type returned from the function.

scala> List("A","Cat").map(_.length)
res24: List[Int] = List(, )
scala> trait Person {def first: String}
defined trait Person

  We can extract data from a collection of complex objects.

scala> val d = new Person{def first = "David"}
d: Person = $anon$@d6ae28
scala> val e = new Person{def first = "Elwood"}
e: Person = $anon$@1281a0
scala> val a = new Person{def first = "Archer"}
a: Person = $anon$@1845cfb
scala> List(a,d,e).map(_.first)
res25: List[String] = List(Archer, David, Elwood)
scala> List(a,d,e).map(a => <li>{a.first}</li>)
res26: List[scala.xml.Elem] = List(<li>Archer</li>, <li>David</li>, <li>Elwood</li>)
# find all the valid Person records, return the first names
scala> trait Person{
| def first : String
| def valid : Boolean
| }
defined trait Person scala> def validByAge(in: List[Person]) = in.filter(_.valid).map(_.first)
validByAge: (in: List[Person])List[String]

5. Reduxio(简化)

  reduceLeft method allows you to perform an operation on adjacent(临近的) of the collection where the result of the first operation is fed into the next operation.

# find the biggest number
scala> List(,,,).reduceLeft(_ max _)
res11: Int =
# find the longest word
scala> List("moos","cow","A","cat").reduceLeft((a,b) => if(a.length > b.length) a else b)
res13: java.lang.String = moos

  reduceLeft throws an exception on an Nil List.

  foldLeft starts with a seed value. The return type of the function and the return type of foldLeft must be same type as the seed.

# foldLeft feeds the seed and the first element of the List, 1, into the function, which returns 1.
scala> List(,,,).foldLeft()(_ + _)
res15: Int =
scala> List("b","a","elwood","archer").foldLeft()(_ + _.length)
res19: Int =

  Sometimes you may need to work with more than one collection at a time.

scala> val n =( to ).toList
n: List[Int] = List(, , )
scala> n.map(i => n.map(j => i * j))
res20: List[List[Int]] = List(List(, , ), List(, , ), List(, , ))

  In order to nest the map operations but flatten the results of nested operations, we use flatMap method:

scala> n.flatMap(i => n.map(j => i * j))
res23: List[Int] = List(, , , , , , , , )

  However , syntactically, nested map, flatMap, and filter can get ugly.

scala> def isOdd(int: Int) = int %  ==
isOdd: (int: Int)Boolean
scala> def isEven(int: Int) = !isOdd(int)
isEven: (int: Int)Boolean
scala> val n = ( to ).toList
n: List[Int] = List(, , , , , , , , , )
scala> n.filter(isEven).flatMap(i => n.filter(isOdd).map(j => i * j))
res25: List[Int] = List(, , , , , , , , ...,, , , , , , , )

  Using for comprehension, we can convert nested statements from the previous example into a syntactically pleasing statement.

scala> for{i <- n if isEven(i); j <- n if isOdd(j)} yield i * j
res31: List[Int] = List(, , , , , ..., , , , , , , , , , , )

6. Range

Ranges are often used to populate data structures, and to iterate over for loops.

scala>  to
res32: scala.collection.immutable.Range.Inclusive = Range(, , , , , , , , , )
scala> until
res33: scala.collection.immutable.Range = Range(, , , , , , , , )
scala> to by
res34: scala.collection.immutable.Range = Range(, , , , )
scala> 'a' to 'c'
res35: scala.collection.immutable.NumericRange.Inclusive[Char] = NumericRange(a, b, c)
scala> val x = ( to ).toList
x: List[Int] = List(, , , , , , , , , )

7. Stream

  A Stream is like a List, except that its elements are computed lazily. A Stream can be constructed with the #:: method, using Stream.Empty at the end of the expression instead of Nil.

# The number  and a ? to denote the end of the stream because the end of the stream hasn't # been evaluated yet.
scala> val stream = #:: #:: #:: Stream.empty
stream: scala.collection.immutable.Stream[Int] = Stream(, ?)
# A Stream can be long ... infinitely long.
scala> val stream = ( to ).toStream
stream: scala.collection.immutable.Stream[Int] = Stream(, ?)
# You can attempt access the head and tail of the stream. The head is returned immediately. But the tail isn't evaluated yet
scala> stream.head
res37: Int =
scala> stream.tail
res38: scala.collection.immutable.Stream[Int] = Stream(, ?)

8. Tuples

scala> def sumSq(in: List[Double]):(Int, Double, Double) =
| in.foldLeft((,0d,0d))((t,v) => (t._1 + , t._2 + v, t._3 + v * v))
sumSq: (in: List[Double])(Int, Double, Double)

  The compiler will treat a collection of elements in parentheses as a Tuple. We seed the foldLeft with (0, 0d, 0d), which the compiler translates to a Tuples[Int, Double, Double]. The param t is a Tuple3, and v is a Double.

  Using pattern matching to make the code a little more readable:

scala> def sumSq(in: List[Double]): (Int, Double, Double) =
| in.foldLeft((, 0d, 0d)){
| case ((cnt,sum,sq), v) => (cnt +, sum + v, sq + v * v)}
sumSq: (in: List[Double])(Int, Double, Double)

  Create Tuples:

scala> Tuple(,) == Pair(,)
res44: Boolean = true
scala> Pair(,) == (,)
res46: Boolean = true
scala> (,) == ( -> )
res49: Boolean = true

9. Map[K,V]

  The default Scala Map class is immutable. This means that you can pass an instance of Map to another thread, and that thread can access the Map without synchronizing.

scala> var p = Map( -> "David",  -> "Elwood")
p: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> David, -> Elwood)

  We create a new Map by passing a set of Pair[Int, String] to the Map object's apply method. We create a var p other than a val p. This because the Map is immutable, so when we alter the contents on the Map, we have to assign the new Map back to p.

# add an element
scala> p + ( -> "Archer")
res1: scala.collection.immutable.Map[Int,String] = Map( -> David, -> Elwood, -> Archer)
# didn't change the immutable Map
scala> p
res2: scala.collection.immutable.Map[Int,String] = Map( -> David, -> Elwood)
# update p
scala> p = p + ( -> "archer")
p: scala.collection.immutable.Map[Int,String] = Map( -> David, -> Elwood, -> archer)
# get element out of the Map
scala> p()
res5: String = Elwood
# Key not found
scala> p()
java.util.NoSuchElementException: key not found:

  The get() Method on Map  returns an Option(Some or Not) that contains the result:

scala> p.get()
res7: Option[String] = None
scala> p.get()
res8: Option[String] = Some(Elwood)

  You can return a default value if the key not found:

scala> p.getOrElse(,"Nobody")
res9: String = Nobody
scala> p.getOrElse(,"Nobody")
res11: String = David
scala> to flatMap(p.get)
res13: scala.collection.immutable.IndexedSeq[String] = Vector(David, Elwood)
# remove elements
scala> p -=
scala> p
res16: scala.collection.immutable.Map[Int,String] = Map( -> Elwood, -> Archer)
# check if Map contains a particular key
scala> p.contains()
res17: Boolean = true
# find the largest key
scala> p.keys.reduceLeft(_ max _)
res18: Int =
# find the largest String
scala> p.values.reduceLeft((a,b) => if (a>b) a else b)
res19: String = Elwood
# value contains the letter "z"
scala> p.values.exists(_.contains("z"))
res21: Boolean = false
# add a bunch of elements using the ++ mthod
scala> p ++= List( -> "Cat", -> "Dog")
scala> p
res23: scala.collection.immutable.Map[Int,String] = Map( -> Elwood, -> Archer, -> Cat, -> Dog)
# remove a bunch of keys with the – metod
scala> p --= List(,)
scala> p
res25: scala.collection.immutable.Map[Int,String] = Map( -> Elwood, -> Cat)
# a simpler way to remove unwanted elements from a Map
def removeInvalid(in: Map[Int, Person]) = in.filter(kv => kv._2.valid)

10. Mutable Collections

  The immutable collections can be transformed into new collections.

scala> val immutableMap = Map( -> "a",  -> "b",  -> "c")
immutableMap: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> a, -> b, -> c)
scala> val newMap = immutableMap - + ( -> "d")
newMap: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> b, -> c, -> d)
# The original collection
scala> immutableMap
res0: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> a, -> b, -> c)

  The List, Map and Set immutable collections can all be converted to the collection.mutable.Buffer type with the toBuffer method.

scala> val m = Map( -> "a",  -> "b")
m: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> a, -> b)
scala> val b = m.toBuffer
b: scala.collection.mutable.Buffer[(Int, java.lang.String)] = ArrayBuffer((,a), (,b))
# The map, containing key-value pairs, is now a sequence of tuples.
scala> b += ( -> "c")
res1: b.type = ArrayBuffer((,a), (,b), (,c))
# changing the buffer to map again
scala> val newMap = b.toMap
newMap: scala.collection.immutable.Map[Int,java.lang.String] = Map( -> a, -> b, -> c)

11. Mutable Queue

  A queue is FIFO data structure. You can create an empty, mutable queue of any data type. Remind that make sure to include the full package name for the type.

# create a Queue
scala> import scala.collection.mutable.Queue
import scala.collection.mutable.Queue
scala> var ints = Queue[Int]()
ints: scala.collection.mutable.Queue[Int] = Queue()

  Add elements to it using +=, ++= and enqueue

# add elements to the Queue
scala> ints +=
res2: scala.collection.mutable.Queue[Int] = Queue()
scala> ints += (,)
res3: scala.collection.mutable.Queue[Int] = Queue(, , )
scala> ints ++= Queue(,)
res5: scala.collection.mutable.Queue[Int] = Queue(, , , , )
# use enqueue
scala> ints.enqueue(,)
scala> ints
res15: scala.collection.mutable.Queue[Int] = Queue(, , , ,,,)

  You typically remove elements from the head of the queue, one element at a time, using dequeue.

scala> ints.dequeue
res18: Int =
scala> ints
res19: scala.collection.mutable.Queue[Int] = Queue(, , , )

  Queue extends from Iterable and Traversable, so it has all the usual collection methods, including foreach, map and so on.

12. Mutable Stack
  A Stack is a LIFO data structure.

# create a Stack
scala> import scala.collection.mutable.Stack
import scala.collection.mutable.Stack
scala> var ints = Stack[Int]()
ints: scala.collection.mutable.Stack[Int] = Stack()
scala> val ints = Stack(,,)
ints: scala.collection.mutable.Stack[Int] = Stack(, , )
# push elements onto the stack with push
scala> ints.push()
res20: ints.type = Stack(, , , )
scala> ints.push(,,)
res21: ints.type = Stack(, , , , , , ) # To take elements off the stack, pop them off the top of the stack
scala> val lastele = ints.pop
lastele: Int =

Beginning Scala study note(6) Scala Collections的更多相关文章

  1. Beginning Scala study note(9) Scala and Java Interoperability

    1. Translating Java Classes to Scala Classes Example 1: # a class declaration in Java public class B ...

  2. Beginning Scala study note(8) Scala Type System

    1. Unified Type System Scala has a unified type system, enclosed by the type Any at the top of the h ...

  3. Beginning Scala study note(3) Object Orientation in Scala

    1. The three principles of OOP are encapsulation(封装性), inheritance(继承性) and polymorphism(多态性). examp ...

  4. Beginning Scala study note(2) Basics of Scala

    1. Variables (1) Three ways to define variables: 1) val refers to define an immutable variable; scal ...

  5. Beginning Scala study note(4) Functional Programming in Scala

    1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...

  6. Beginning Scala study note(1) Geting Started with Scala

    1. Scala is a contraction of "scalable" and "language". It's a fusion of objecte ...

  7. Beginning Scala study note(7) Trait

    A trait provides code reusability in Scala by encapsulating method and state and then offing possibi ...

  8. Beginning Scala study note(5) Pattern Matching

    The basic functional cornerstones of Scala: immutable data types, passing of functions as parameters ...

  9. Scala进阶之路-Scala中的Ordered--Ordering

    Scala进阶之路-Scala中的Ordered--Ordering 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   说道对象的比较,在Java中大家最熟悉不过的就是实现类本身实 ...

随机推荐

  1. Could not find or load main class org.gradle.wrapper.GradleWrapperMain解决办法

    解决办法: gradlew is the gradle wrapper executable - batch script on windows and shell script elsewhere. ...

  2. Codeforces Round #352 (Div. 2) ABCD

    Problems     # Name     A Summer Camp standard input/output 1 s, 256 MB    x3197 B Different is Good ...

  3. centos7 cannot find a valid baseurl for repo base (转载)

    centos7 cannot find a valid baseurl for repo base     今天在虚拟机下安装centosmini版本,安装后第一件事就是yum update 但是有错 ...

  4. 10、代码块、构造代码块、静态代码块及main方法之间的关系

    1.普通代码块: 在方法或语句中出现在{}之间的类容就称为普通代码块,简称代码块.普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”,即顺序执行. /*下面第一个类时合法的 ...

  5. SQL Server触发器

    一﹕ 触发器是一种特殊的存储过程﹐它不能被显式地调用﹐而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活.所以触发器可以用来实现对表实施复杂的完整性约`束. 二﹕ SQL Server为每个触发 ...

  6. Spring_的jar详细说明

    org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spring 2.5.6的时候需要a ...

  7. ZOJ Problem Set - 3329(概率DP)

    One Person Game Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge There is a very ...

  8. HDU 2296 Ring -----------AC自动机,其实我想说的是怎么快速打印字典序最小的路径

    大冥神的代码,以后能贴的机会估计就更少了....所以本着有就贴的好习惯,= =....直接贴 #include <bits/stdc++.h> using LL = long long ; ...

  9. tfs连不上团队资源管理器问题

    这个问题主要原因是因电脑装了vs2008又装了vs2012,因为版本不一样,所以只需要将VersionControl.config这个文件删除掉就可以了.文件路径C:\Users\Administra ...

  10. GridLayout 使用

    上次做了一个小键盘,请见:PopupWindow 使用. 效果是这样的: 可以看到,上面的按键是不一样大小的.因为是用LinearLayout布局,用的Button样式也是默认的.数字键和文字键的大小 ...