scala-collection

Scala的集合類可以從三個維度進行切分:

可變與不可變集合(Immutable and mutable collections)

靜態與延遲加載集合 (Eager and delayed evaluation )

串行與并行計算集合(Sequential and parallel evaluation )

transformation,集合中有大量的操作都是把一個集合“轉換”成另一個集合,比如map,filter等等。而Eager和Delayed集合的區別在于:Eager集合總是立即為元素分配內存,當遇到一個transform動作時,Eager的集合會直接計算并返回結果,而Delayed集合則會盡可能晚的推遲執行,直到必須返回結果時才去執行。這一點和Spark RDD操作中的transformation和action非常類似。

在現有的集合里,只有Stream是Lasy的,所有其他的集合都是靜態(Eager)加載的。但是你可以很容易地把一個靜態集合轉換成lazy的,那就是創建一個view

集合類型總覽

Immutable?Collection

Immutable Seq

Seq主要分兩大類:indexed sequences和linear sequences,indexed sequences暗示本類集合在隨機讀取方面有較高的性能(類似數據結構中的數組)。linear sequences暗示本類集合在head和tail操作和順序遍歷上更有優勢(類似于數據結構中的雙向列表

在使用Seq時,默認使用的具體類是List, 使用IndexedSeq時默認使用的具體類是Vector.

scala> val seq = Seq(1,2,3)seq: Seq[Int]= List(1,2,3)scala> val indexedSeq = IndexedSeq(1,2,3)indexedSeq: IndexedSeq[Int]= Vector(1,2,3)

Immutable Set

Immutable Map

Mutable Seq

如何選擇集合類

各種Immutable Sequence的特性比較

各種Mutable Sequence的特性比較

各種Map的特性比較

各種Set的特性比較


一、常用操作符(操作符其實也是函數)

++ ++[B](that: GenTraversableOnce[B]): List[B] 從列表的尾部添加另外一個列表

++: ++:[B >: A, That](that: collection.Traversable[B])(implicit bf: CanBuildFrom[List[A], B, That]): That 在列表的頭部添加一個列表

+: +:(elem: A): List[A] 在列表的頭部添加一個元素

:+ :+(elem: A): List[A] 在列表的尾部添加一個元素

:: ::(x: A): List[A] 在列表的頭部添加一個元素

::: :::(prefix: List[A]): List[A] 在列表的頭部添加另外一個列表

:\ :[B](z: B)(op: (A, B) ?6?0 B): B 與foldRight等價

val left = List(1,2,3)

val right = List(4,5,6)

//以下操作等價

left ++ right? // List(1,2,3,4,5,6)

left ++: right? // List(1,2,3,4,5,6)

right.++:(left)? ? // List(1,2,3,4,5,6)

right.:::(left)? // List(1,2,3,4,5,6)

//以下操作等價

0 +: left? ? //List(0,1,2,3)

left.+:(0)? //List(0,1,2,3)

//以下操作等價

left :+ 4? ? //List(1,2,3,4)

left.:+(4)? //List(1,2,3,4)

//以下操作等價

0 :: left? ? ? //List(0,1,2,3)

left.::(0)? ? //List(0,1,2,3)

任何以冒號結果的操作符,都是右綁定的,即 0 :: List(1,2,3) = List(1,2,3).::(0) = List(0,1,2,3) 從這里可以看出操作::其實是右邊List的操作符,而非左邊Int類型的操作符


5.util包

5.1.架構

http://www.scala-lang.org/docu/files/collections-api/collections.html

The following figure shows all collections in packagescala.collection. These are all high-level abstract classes or traits, which generally have mutable as well as immutable implementations.

The main trait isIterable,which is the supertrait of both mutable and immutable variations of sequences (Seqs), sets, and maps. Sequences are ordered collections, such as arrays and lists. Sets contain at most one of each object, as determined by the==method. Maps contain acollectionof keys mapped to values.

Sequences, classes that inherit from traitSeq,let you work with groups of data lined up in order. Because the elements are ordered, you can ask for the first element, second element, 103rd element, and so on.

scala.collection.immutable

The immutability helps you develop correct, efficient algorithms because you never need to make copies of acollection.

scala.collection.mutable

不可變(collection.immutable._)

可變(collection.mutable._)

Array

ArrayBuffer

List

ListBuffer

String

StringBuilder

/

LinkedList, DoubleLinkedList

List

MutableList

/

Queue

Array

ArraySeq

Stack

Stack

HashMap HashSet

HashMap HashSet

ArrayStack

5.2.集合Array,List,Tuple

Array

長度固定

元素可變

確定長度,后賦值;

List

長度固定

元素不可變

Tuple

長度固定

元素不可變

常用于有多個返回值的函數;或者多個變量的同時定義

Scala2.8中,3者的元素都可以混合不同的類型(轉化為Any類型);

Scala2.7中,Array、List都不能混合類型,只有Tuple可以;

Arraysallow 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.

Listssupport fast addition and removal of items to the beginning of the list, but theydo notprovidefast accessto arbitrary indexes because theimplementation must iterate through the list linearly.

5.2.1.定義和初始化

5.2.1.1Array

val list1 = new Array[String](0) // Array()

val list2 = new Array[String](3) // Array(null, null, null)

val list3:Array[String] = new Array(3) // // Array(null, null, null)

val list1 = Array("a","b","c","d") //相當于Array.apply("a","b","c","d")

定義一個類型為Any的Array:

val aa = Array[Any](1, 2)

或:

val aa: Array[Any] = Array(1, 2)

或:

val aa: Array[_] = Array(1, 2)

定義:

Array (1,3,5,7,9,11)

也可以用

Array[Int](1 to 11 by 2:_*)

暫時還沒有找到Range(例如 1 to 11 by 2)之后跟:_*的依據

Array對應的可變ArrayBuffer:

val ab =collection.mutable.ArrayBuffer[Int]()

ab += (1,3,5,7)

ab ++= List(9,11) // ArrayBuffer(1, 3, 5, 7, 9, 11)

ab toArray // Array (1, 3, 5, 7, 9, 11)

ab clear // ArrayBuffer()

5.2.1.2List

val list:List[Int]= List(1,3,4,5,6) //或者List(1 to 6:_*)

val list1 = List("a","b","c","d") //或者List('a' to 'd':_*) map (_.toString)

元素合并進List用::

val list2 = "a"::"b"::"c"::Nil // Nil是必須的

val list3 = "begin" :: list2 // list2不變,只能加在頭,不能加在尾

多個List合并用++,也可以用:::(不如++)

val list4 = list2++"end"++Nil

val list4 = list2:::"end" :: Nil //相當于list2 ::: List("end")

當import java.util._之后會產生沖突,需要指明包

scala.List(1,2,3)

List對應的可變ListBuffer:

val lb =scala.collection.mutable.ListBuffer(1,2,3)

lb.append(4) // ListBuffer(1, 2, 3, 4)

val lb =collection.mutable.ListBuffer[Int]()

lb += (1,3,5,7)

lb ++= List(9,11) // ListBuffer(1, 3, 5, 7, 9, 11)

lb.toList // List(1, 3, 5, 7, 9, 11)

lb.clear // ListBuffer()

建議定義方式:

val head::body = List(4,"a","b","c","d")

// head: Any = 4

// body: List[Any] = List(a, b, c, d)

val a::b::c = List(1,2,3)

// a: Int = 1

// b: Int = 2

// c: List[Int] = List(3)

定義固定長度的List:

List.fill(10)(2)// List(2, 2, 2, 2, 2, 2, 2, 2, 2, 2)

Array.fill(10)(2)// Array(2, 2, 2, 2, 2, 2, 2, 2, 2, 2)

又如:

List.fill(10)(scala.util.Random.nextPrintableChar)

// List(?, =, ^, L, p, <, \, 4, 0, !)

List.fill(10)(scala.util.Random.nextInt(101))

// List(80, 45, 26, 75, 24, 72, 96, 88, 86, 15)

5.2.1.3Tuple

val t1 = ("a","b","c")

var t2 = ("a", 123, 3.14, new Date())

val (a,b,c) = (2,4,6)

最簡單的Tuple:

1->"hello world"

和下面的寫法是等價的:

(1, "hello world")

To access elements of a tuple, you can use method_1to access the first element,_2to access the second, and so on:

scala> val v = (1, "Nick", 43)

scala> v._1

res179: Int = 1

scala> v._2

res180: String = Nick

scala> v._3

res181: Int = 43

5.2.1.4Vector

Scala2.8為了提高list的隨機存取效率而引入的新集合類型(而list存取前部的元素快,越往后越慢)。

val v = Vector.empty

val v2 = 0+:v:+10:+20 // Vector(0, 10, 20), Vector那一邊始終有":"

v2(1) // 10

v2updated(1,100) // Vector(0, 100, 20)

這個例子舉的不太好,scala.collection.immutable. Vector擴展、updated之后是新生成的vector,原vector保持immutable。這點和List類似。

Seq的缺省實現是List:

Seq(1,2,3) // List(1, 2, 3)

IndexSeq的缺省實現是Vector:

IndexSeq(1,2,3) // Vector(1, 2, 3)

5.2.1.5Range

Range(0, 5) // (0,1,2,3,4)

等同于:

0 until 5

等同于:

0 to 4

兩個Range相加:

('0' to '9') ++ ('A' to 'Z') // (0,1,..,9,A,B,...,Z)

Range和序列轉換:

1 to 5 toList

相當與:

List(1 to 5:_*)

或者:

Vector(1 to 5: _*) // Vector(1,2,3,4,5)

5.2.1.6Stack Queue (List類的sibling)

先進后出的堆棧:

val s =collection.immutable.Stack()

You push an element onto a stack withpush, pop an element withpop, and peek at the top of the stack without removing it withtop/head.

val s2 = s.push(10,20,30) // Stack(30, 20, 10)

s2.head// 30

s2.pop.pop // Stack(10)

對應的可變Stack:

val ms =collection.mutable.Stack()

ms.push(1,3,5).push(7) // Stack(7, 5, 3, 1)

ms.head // 7

ms.pop // 7, ms = Stack(5,3,1)

先進先出的隊列:

val q =collection.immutable.Queue() //也可指定類型Queue[Int]()

//You can append an element to an immutable queue withenqueue:

val q2 = q.enqueue(0).enqueue(List(10,20,30)) // Queue(0, 10, 20, 30)

//To remove an element from the head of the queue, you usedequeue:

q2.dequeue._1 // 0

q2.dequeue._2 // Queue(10, 20, 30)

On immutable queues, thedequeuemethod returns a pair (aTuple2) consisting of the element at the head of the queue, and the rest of the queue with the head element removed.

val qHas123 = Queue(1,2,3)

scala>val(element,?has23)?=?qHas123.dequeueelement:?Int?=?1has23:scala.collection.immutable.Queue[Int]?=?Queue(2,3)

對應的可變Queue:

You use a mutable queue similarly to how you use an immutable one, but instead ofenqueue, you use the+=and++=operators to append. Also, on a mutable queue, thedequeuemethod will just remove the head element from the queue and return it.

val mq =collection.mutable.Queue[Int]()

mq+=(1,3,5)

mq++=List(7,9) // Queue(1, 3, 5, 7, 9)

mq dequeue // 1, mq= Queue(3, 5, 7, 9)

mq clear // Queue()

If you need a first-in-first-out sequence, you can use aQueue.

If you need a last-in-first-out sequence, you can use aStack.

5.2.1.7Stream

Stream相當于lazy List,避免在中間過程中生成不必要的集合。

定義生成:

val st = 1#::2#::3#::Stream.empty // Stream(1, ?)

例子:fib數列的Stream版本簡單易懂

def fib(a: Int, b: Int): Stream[Int] = a#::fib(b,? a+b)

valfibs = fib(1, 1).take(7).toList // List(1, 1, 2, 3, 5, 8, 13)

fib數列的前后項比值趨于黃金分割:

def fn(n:Int) = fib(1,1)(n)

1 to 10 map (n=> 1.0*fn(n)/fn(n+1)) // Vector(0.5, 0.666, ..., 0.618)

例子1:

Range(1,50000000).filter (_ % 13==0)(1) // 26,但很慢,需要大量內存

Stream.range(1,50000000).filter(_%13==0)(1) // 26,很快,只計算最終結果需要的內容

注意:

第一個版本在filter后生成一個中間collection,size=50000000/13;而后者不生成此中間collection,只計算到26即可。

例子2:

(1 to 100).map(i=> i*3+7).filter(i=> (i%10)==0).sum // map和filter生成兩個中間collection

(1 to 100).toStream.map(i=> i*3+7).filter(i=> (i%10)==0).sum

5.2.2.使用(map, flatMap, filter, exists等)

5.2.2.1map

//類型可以混合:

import java.util._

val list3 = Array("a", 123, 3.14, new Date())

List("a","b","c").map(s=>s.toUpperCase()) //方式1

List("a","b","c").map(_.toUpperCase()) ????//方式2,類似于Groovy的it

// = List(A, B, C)

5.2.2.2filter filterNot

List(1,2,3,4,5).filter(_%2==0) // List(2, 4)

也可以寫成:

for (x<-List(1,2,3,4,5) if x%2==0) yield x

List(1,2,3,4,5).filterNot(_%2==0) // List(1, 3, 5)

5.2.2.3partition span splitAt groupBy

注:val (a,b) = List(1,2,3,4,5).partition(_%2==0) // (List(2,4), List(1,3,5))

可把Collection分成:滿足條件的一組,其他的另一組。

和partition相似的是span,但有不同:

List(1,9,2,4,5).span(_<3)// (List(1),List(9, 2, 4, 5)),碰到不符合就結束

List(1,9,2,4,5).partition(_<3)// (List(1, 2),List(9, 4, 5)),掃描所有

List(1,3,5,7,9)splitAt2// (List(1, 3),List(5, 7, 9))

List(1,3,5,7,9)groupBy(5<)// Map((true,List(7, 9)), (false,List(1, 3, 5)))

5.2.2.4foreach

打印:

Array("a","b","c","d").foreach(printf("[%s].",_))

// [a].[b].[c].[d].

5.2.2.5exists

//集合中是否存在符合條件的元素

List(1,2,3,4,5).exists(_%3==0) // true

5.2.2.6find

返回序列中符合條件的第一個。

例子:查找整數的第一個因子(最小因子、質數)

def fac1(n:Int) = if (n>= -1 && n<=1) n else (2 to n.abs) find (n%_==0) get

5.2.2.7sorted sortWith sortBy

例子(排序):

List(1,3,2,0,5,9,7).sorted//List(0, 1, 2, 3, 5, 7, 9)

List(1,3,2,0,5,9,7).sortWith(_>_)// List(9, 7, 5, 3, 2, 1, 0)

List("abc", "cb", "defe", "z").sortBy(_.size) //List(z, cb, abc, defe)

List((1,'c'), (1,'b'), (2,'a')).sortBy(_._2)// List((2,a), (1,b), (1,c))

5.2.2.8distinct

例子:(去除List中的重復元素)

def uniq[T](l:List[T]) = l.distinct

uniq(List(1,2,3,2,1)) // List(1,2,3)

5.2.2.9flatMap

flatMap的作用:把多層次的數據結構“平面化”,并去除空元素(如None)。

可用于:得到xml等樹形結構的所有節點名稱,去除None等

例子1a:(兩個List做乘法)

List(1,2,3) * List(10,20,30) = List(10, 20, 30,20, 40, 60,30, 60, 90)

val (a,b) = (List(1,2,3), List(10,20,30))

aflatMap(i=> b map (j=> i*j))

等同于:

for (i<-a; i<-b) yield i*j //這個寫法更清晰

例子1b:

如果不用flatMap而是用map,結果就是:

amap(i=> b map (j=> i*j))// List(List(10, 20, 30), List(20, 40, 60), List(30, 60, 90))

等同于:

for (i<-a) yield { for (j<-b) yield i*j } //不如上面的清晰

例子2:

List("abc","def") flatMap (_.toList) // List(a, b, c, d, e, f)

List("abc","def") map (_.toList) // List(List(a, b, c), List(d, e, f))

例子3:flatMap結合Option

def toint(s:String) =

try { Some(Integer.parseInt(s)) } catch { case e:Exception => None }

List("123", "12a", "45") flatMap toint // List(123, 45)

List("123", "12a", "45") map toint // List(Some(123), None, Some(45))

5.2.2.10indices,zipWithIndex, slice

得到indices:

val a = List(100,200,300)

aindices// (0,1,2)

azipWithIndex// ((100,0), (200,1), (300,2))

(a indices) zip a // ((0,100), (1,200), (2,300))

截取一部分,相當于String的substring

List(100,200,300,400,500)slice(2,4) // (300,400),取l(2), l(3)

5.2.2.11take drop splitAt

List(1,3,5,7) take 2 // List(1,3)

List(1,3,5,7) drop 2 // List(5,7)

5.2.2.12count

滿足條件的元素數目:

例如1000內質數的個數:

def prime(n:Int) = if (n<2) false else 2 to math.sqrt(n).toInt forall (n%_!=0)

1 to 1000countprime? // 168

5.2.2.13updated patch

對于immutable的數據結構,使用updated返回一個新的copy:

val v1 = List(1,2,3,4)

v1.updated(3,10) // List(1, 2, 3,10), v1還是List(1, 2, 3,4)

對于可變的數據結構,直接更改:

val mseq =scala.collection.mutable.ArraySeq(1, 2, 4,6)

mseq(3) = 10 // mseq = ArraySeq(1, 2, 4,10)

批量替換,返回新的copy:

val v1 = List(1,2,3,4,5)

val v2 = List(10,20,30)

v1 patch (0, v2, 3) // List(10,20,30,4,5),但v1,v2不變

5.2.2.14reverse reverseMap

1 to 5reverse// Range(5, 4, 3, 2, 1)

"james".reverse.reverse // "james"

reverseMap就是revese + map

1 to 5reverseMap(10*) // Vector(50, 40, 30, 20, 10)

相當于:

(1 to 5 reverse) map (10*)

5.2.2.15contains startsWith endWith

1 to 5contains3 // true,后一個參數是1個元素

1 to 5containsSlice(2 to 4) // true,后一個參數是1個集合

(1 to 5)startsWith(1 to 3) // true后一個參數是1個集合

(1 to 5)endsWith(4 to 5)

(List(1,2,3)correspondsList(4,5,6)) (_<_)// true,長度相同且每個對應項符合判斷條件

5.2.2.16集合運算

List(1,2,3,4)intersectList(4,3,6) //交集= List(3, 4)

List(1,2,3,4)diffList(4,3,6) // A-B = List(1, 2)

List(1,2,3,4)unionList(4,3,6) // A+B = List(1, 2, 3, 4, 4, 3, 6)

//相當于

List(1,2,3,4)++List(4,3,6) // A+B = List(1, 2, 3, 4, 4, 3, 6)

5.2.2.17殊途同歸

例子:得到(4, 16, 36, 64, 100)

寫法1:

(1 to 10)filter(_%2==0)map(x=>x*x)

寫法2:

for(x<-1 to 10ifx%2==0)yieldx*x

寫法3:

(1 to 10)collect{casexifx%2==0 => x*x }

5.2.2.18其他

對其他語言去重感興趣,可看看:

http://rosettacode.org/wiki/Remove_duplicate_elements

5.2.3.數組元素定位

統一使用(),而不是[],()就是apply()的簡寫,a(i)===a.apply(i)

// Array

val a = Array(100,200,300) // a(0)=100, a(1)=200, a(3)=300

a(0) // 100,相當于a.apply(0)

a(0)=10 // Array(10, 200, 300),相當于a.update(0, 10)

// List

val list = List("a","b","c")

// list(0)=="a", list(1)=="b", list(2)=="c"

由于List不是index sequence,定位訪問成本高,不建議使用。同樣不建議使用的還有List 的 length

// Tuple

val t1 = ("a","b","c") // t1._1="a", t1._2="b", t1._3="c"

5.2.4.view

在某類型的集合對象上調用view方法,得到相同類型的集合,但所有的transform函數都是lazy的,從該view返回調用force方法。

對比:

val v = Vector(1 to 10:_*)

v map (1+) map (2*) //Vector(4,?6,?8,?10,?12,?14,?16,?18,?20,?22)

以上過程得生成2個新的Vector,而:

val v = Vector(1 to 10:_*)

v.view map (1+) map (2*) force

只在過程中生成1個新的Vector,相當于:

v map (x=>2*(1+x))

又如:

((1 to 1000000000) view).take(3).force // Vector(1,2,3)

使用Stream:

Stream.range(1,1000000000).take(3).force // ?Stream(1, 2, 3)

5.2.5.和Java集合間的轉換(scalaj)

方案一:Java的List很容易通過List.toArray轉換到Array,和Scala中的Array是等價的,可使用map、filter等。

方案二:使用第三方的scalaj擴展包(需自行下載設置classpath)

例子1:

val a1 = new java.util.ArrayList[Int]

a1.add(100); a1.add(200); a1.add(300)

//自行轉換

val a2 = a1.toArray

a2 map (e=>e.asInstanceOf[Int]) map(2*) filter (300>)

//采用scalaj(http://github.com/scalaj/scalaj-collection)

import scalaj.collection.Imports._

val a3 = a1.asScala

//scala->java

List(1, 2, 3).asJava

Map(1 -> "a", 2 -> "b", 3 -> "c").asJava

Set(1, 2, 3).asJava

// scalaj還可以在java的collection上使用foreach (目前除foreach外,還不支持filter、map)

a1.foreach(println)

scalaj的簡易文檔如下:

//Java toScala

Java類型

轉換方法

java.lang.Comparable[A]

#asScala:scala.math.Ordered[A]

java.util.Comparator[A]

#asScala:scala.math.Ordering[A]

java.util.Enumeration[A]

#asScala:scala.collection.Iterator[A]

#foreach(A => Unit): Unit

java.util.Iterator[A]

#asScala:scala.collection.Iterator[A]

#foreach(A => Unit): Unit

java.lang.Iterable[A]

#asScala:scala.collection.Iterable[A]

#foreach(A => Unit): Unit

java.util.List[A]

#asScala:scala.collection.Seq[A]

#asScalaMutable:scala.collection.mutable.Seq[A]

java.util.Set[A]

#asScala:scala.collection.Set[A]

#asScalaMutable:scala.collection.mutable.Set[A]

java.util.Map[A, B]

#asScala:scala.collection.Map[A, B]

#asScalaMutable:scala.collection.mutable.Map[A, B]

#foreach(((A, B)) => Unit): Unit

java.util.Dictionary[A, B]

#asScala:scala.collection.mutable.Map[A, B]

#foreach(((A, B)) => Unit): Unit

//Scalato Java

Scala類型

轉換方法

scala.math.Ordered[A]

#asJava: java.util.Comparable[A]

scala.math.Ordering[A]

#asJava: java.util.Comparator[A]

scala.collection.Iterator[A]

#asJava: java.util.Iterator[A]

#asJavaEnumeration: java.util.Enumeration[A]

scala.collection.Iterable[A]

#asJava: java.lang.Iterable[A]

scala.collection.Seq[A]

#asJava: java.util.List[A]

scala.collection.mutable.Seq[A]

#asJava: java.util.List[A]

scala.collection.mutable.Buffer[A]

#asJava: java.util.List[A]

scala.collection.Set[A]

#asJava: java.util.Set[A]

scala.collection.mutable.Set[A]

#asJava: java.util.Set[A]

scala.collection.Map[A, B]

#asJava: java.util.Map[A, B]

scala.collection.mutable.Map[A, B]

#asJava: java.util.Map[A, B]

#asJavaDictionary: java.util.Dictionary[A, B]

5.3.Map

5.3.1.定義Map

var m = Map[Int, Int]()

var m = Map(1->100, 2->200)

或者

var m = Map((1,100), (2,200))

相加:

val m = Map(1->100, 2->200)++Map(3->300)//Map((1,100), (2,200), (3,300))

可以用zip()生成Map:

List(1,2,3).zip(List(100,200,300)).toMap// Map((1,100), (2,200), (3,300))

注解:zip有“拉拉鏈”的意思,就是把兩排鏈扣完全對應扣合在一起,非常形象。

5.3.2.不可變Map(缺省)

l定義:

val m2 =Map()

val m3 =Map(1->100, 2->200, 3->300)

指定類型:

val m1:Map[Int,String]= Map(1->"a",2->"b")

注:如果import java.util._后發生沖突,可指明:scala.collection.immutable.Map

保持循序的Map可以使用:

collection.immutable.ListMap

l讀取元素:

// m3(1)=100, m3(2)=200, m3(3)=300

// m3.get(1)=Some(100), m3.get(3)=Some(300), m3.get(4)=None

val v = m3.get(4).getOrElse(-1) // -1

或者簡化成:

m3.getOrElse(4, -1) // -1

l增加、刪除、更新:

Map本身不可改變,即使定義為var,update也是返回一個新的不可變Map:

var m4 = Map(1->100)

m4 += (2->200) // m4指向新的(1->100,2->200), (1->100)應該被回收

另一種更新方式:

m4.updated(1,1000)

增加多個元素:

Map(1->100,2->200)+(3->300, 4->400) // Map((1,100), (2,200), (3,300), (4,400))

刪除元素:

Map(1->100,2->200,3->300)-(2,3) // Map((1,100))

Map(1->100,2->200,3->300)--List(2,3) // Map((1,100))

l合并Mpa:

Map(1->100,2->200)++Map(3->300) // Map((1,100), (2,200), (3,300))

5.3.3.可變Map

val map =scala.collection.mutable.Map[String, Any]()

map("k1")=100???? //增加元素,方法1

map += "k2"->"v2" //增加元素,方法2

// map("k2")=="v2", map.get("k2")==Some("v2"), map.get("k3")==None

有則取之,無則加之:

val mm =collection.mutable.Map(1->100,2->200,3->300)

mmgetOrElseUpdate(3,-1) // 300, mm不變

mmgetOrElseUpdate(4,-1) // 300, mm=Map((2,200),(4,-1), (1,100), (3,300))

刪除:

val mm =collection.mutable.Map(1->100,2->200,3->300)

mm-=1 // Map((2,200), (3,300))

mm-=(2,3) // Map()

mm+=(1->100,2->200,3->300) // Map((2,200), (1,100), (3,300))

mm--=List(1,2) // Map((3,300))

mmremove1 // Some(300), mm=Map()

mm+=(1->100,2->200,3->300)

mm.retain((x,y) => x>1) // mm = Map((2,200), (3,300))

mm.clearn// mm = Map()

改變value:

mmtransform((x,y)=> 0) // mm = Map((2,0), (1,0), (3,0))

mm transform ((x,y)=> x*10) // Map((2,20), (1,10), (3,30))

mm transform ((x,y)=> y+3) // Map((2,23), (1,13), (3,33))

5.3.4.Java的HashMap

使用Java的HashMap:

val m1:java.util.Map[Int, String] = new java.util.HashMap

5.3.5.讀取所有元素

上面說過,Map(1->100,2->200,3->300)和Map((1,100),(2,200),(3,300))的寫法是一樣的,可見Map中的每一個entry都是一個Tuple,所以:

for(e<-map) println(e._1 + ": " + e._2)

或者

map.foreach(e=>println(e._1 + ": " + e._2))

或者(最好

for ((k,v)<-map) println(k + ": " + v)

也可以進行filter、map操作:

mapfilter(e=>e._1>1)// Map((2,200), (3,300))

mapfilterKeys(_>1)// Map((2,200), (3,300))

map.map(e=>(e._1*10, e._2)) // Map(10->100,20->200,30->300)

mapmap(e=>e._2)// List(100, 200, 300)

相當于:

map.values.toList

5.3.6.多值Map

結合Map和Tuple,很容易實現一個key對應的value是組合值的數據結構:

val m = Map(1->("james",20), 2->("qh",30), 3->("qiu", 40))

m(2)._1 // "qh"

m(2)._2 // 30

for((k,(v1,v2))<- m ) printf("%d: (%s,%d)\n", k, v1, v2)

5.3.7.Common operations for maps

What it isWhat it does

valnums=Map("i"->1,"ii"->2)Creates an immutable map (nums.toStringreturnsMap(i->1,ii->2))

nums+("vi"->6)Adds an entry (returnsMap(i->1,ii->2,vi->6))

nums-"ii"Removes an entry (returnsMap(i->1))

nums++List("iii"->3,"v"->5)Adds multiple entries (returnsMap(i->1,ii->2,iii->3,v->5))

nums--List("i","ii")Removes multiple entries (returnsMap())

nums.sizeReturns the size of the map (returns2)

nums.contains("ii")Checks for inclusion (returnstrue)

nums("ii")Retrieves the value at a specified key (returns2)

nums.keysReturns the keys (returns anIteratorover the strings"i"and"ii")

nums.keySetReturns the keys as a set (returnsSet(i,ii))

nums.valuesReturns the values (returns anIteratorover the integers1and2)

nums.isEmptyIndicates whether the map is empty (returns false)

importscala.collection.mutableMakes the mutable collections easy to access

valwords=

mutable.Map.empty[String,Int]Creates an empty, mutable map

words+=("one"->1)Adds a map entry from"one"to1(words.toStringreturnsMap(one->1))

words-="one"Removes a map entry, if it exists (words.toStringreturnsMap())

words++=List("one"->1,

"two"->2,"three"->3)Adds multiple map entries (words.toStringreturnsMap(one->1,two->2,three->3))

words--=List("one","two")Removes multiple objects (words.toStringreturnsMap(three->3))

5.4.Set

注:BitSet(collection.immutable.BitSet)和Set類似,但操作更快

5.4.1.定義

var s = Set(1,2,3,4,5) //scala.collection.immutable.Set

var s2 = Set[Int]() //scala.collection.immutable.Set[Int]

//增加元素:

s2 += 1? // Set(1)

s2 += 3? // Set(1,3)

s2 += (2,4) // Set(1,3,2,4)

//刪除元素

Set(1,2,3) - 2 // Set(1,3)

Set(1,2,3) - (1,2) // Set(3)

Set(1,2,3).empty // Set()全部刪除

//判斷是否包含某元素

s(3) // true,集合中有元素3

s(0) // false,集合中沒有元素0

//合并

Set(1,2,3)++Set(2,3,4) // Set(1, 2, 3, 4)

Set(1,2,3)--Set(2,3,4) // Set(1)

5.4.2.邏輯運算

運算

例子

交集

Set(1,2,3)&Set(2,3,4) // Set(2,3)

Set(1,2,3)intersectSet(2,3,4)

并集

Set(1,2,3)|Set(2,3,4) // Set(1,2,3,4)

Set(1,2,3)unionSet(2,3,4) // Set(1,2,3,4)

差集

Set(1,2,3)&~Set(2,3,4) // Set(1)

Set(1,2,3)diffSet(2,3,4) // Set(1)

5.4.3.可變BitSet

val bs =collection.mutable.BitSet()

bs += (1,3,5) // BitSet(1, 5, 3)

bs ++= List(7,9) // BitSet(1, 9, 7, 5, 3)

bs.clear // BitSet()

5.4.4.Common operations for sets

What it isWhat it does

valnums=Set(1,2,3)Creates an immutable set (nums.toStringreturnsSet(1,2,3))

nums+5Adds an element (returnsSet(1,2,3,5))

nums-3Removes an element (returnsSet(1,2))

nums++List(5,6)Adds multiple elements (returnsSet(1,2,3,5,6))

nums--List(1,2)Removes multiple elements (returnsSet(3))

nums**Set(1,3,5,7)Takes the intersection of two sets (returnsSet(1,3))

nums.sizeReturns the size of the set (returns3)

nums.contains(3)Checks for inclusion (returnstrue)

importscala.collection.mutableMakes the mutable collections easy to access

valwords=

mutable.Set.empty[String]Creates an empty, mutable set (words.toStringreturnsSet())

words+="the"Adds an element (words.toStringreturnsSet(the))

words-="the"Removes an element, if it exists (words.toStringreturnsSet())

words++=List("do","re","mi")Adds multiple elements (words.toStringreturnsSet(do,re,mi))

words--=List("do","re")Removes multiple elements (words.toStringreturnsSet(mi))

words.clearRemoves all elements (words.toStringreturnsSet())

5.5.Iterator

Iterator不屬于集合類型,只是逐個存取集合中元素的方法:

val it = Iterator(1,3,5,7) // Iterator[Int] = non-empty iterator

it foreach println // 1 3 5 7

it foreach println //無輸出

三種常用的使用模式:

//1、使用while

val it = Iterator(1,3,5,7) 或者 val it = List(1,3,5,7).iterator

while(it.hasNext) println(it.next)

// 2、使用for

for(e<- Iterator(1,3,5,7)) println(e)

//3、使用foreach

Iterator(1,3,5,7)foreachprintln

Iterator也可以使用map的方法:

Iterator(1,3,5,7) map (10*) toList // List(10, 30, 50, 70)

Iterator(1,3,5,7) dropWhile (5>) toList // List(5,7)

由于Iterator用一次后就消失了,如果要用兩次,需要toList或者使用duplicate:

val (a,b) = Iterator(1,3,5,7) duplicate // a = b = non-empty iterator

又如:

val it = Iterator(1,3,5,7)

val (a,b) = it duplicate

//在使用a、b前,不能使用it,否則a、b都不可用了。

a toList // List(1,3,5,7)

b toList // List(1,3,5,7)

//此時it也不可用了

5.6.Paralllelcollection

Scala2.9+引入:

(1 to 10).parforeach println

多運行幾次,注意打印順序會有不同

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容