Scala的集合類可以從三個維度進(jìn)行切分:
可變與不可變集合(Immutable and mutable collections)
靜態(tài)與延遲加載集合 (Eager and delayed evaluation )
串行與并行計算集合(Sequential and parallel evaluation )
transformation,集合中有大量的操作都是把一個集合“轉(zhuǎn)換”成另一個集合,比如map,filter等等缸托。而Eager和Delayed集合的區(qū)別在于:Eager集合總是立即為元素分配內(nèi)存左敌,當(dāng)遇到一個transform動作時,Eager的集合會直接計算并返回結(jié)果俐镐,而Delayed集合則會盡可能晚的推遲執(zhí)行矫限,直到必須返回結(jié)果時才去執(zhí)行。這一點(diǎn)和Spark RDD操作中的transformation和action非常類似佩抹。
在現(xiàn)有的集合里叼风,只有Stream是Lasy的,所有其他的集合都是靜態(tài)(Eager)加載的匹摇。但是你可以很容易地把一個靜態(tài)集合轉(zhuǎn)換成lazy的咬扇,那就是創(chuàng)建一個view。
集合類型總覽
Immutable?Collection
Immutable Seq
Seq主要分兩大類:indexed sequences和linear sequences,indexed sequences暗示本類集合在隨機(jī)讀取方面有較高的性能(類似數(shù)據(jù)結(jié)構(gòu)中的數(shù)組)廊勃。linear sequences暗示本類集合在head和tail操作和順序遍歷上更有優(yōu)勢(類似于數(shù)據(jù)結(jié)構(gòu)中的雙向列表)
在使用Seq時,默認(rèn)使用的具體類是List, 使用IndexedSeq時默認(rèn)使用的具體類是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的特性比較
一经窖、常用操作符(操作符其實(shí)也是函數(shù))
++ ++[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)
任何以冒號結(jié)果的操作符坡垫,都是右綁定的,即 0 :: List(1,2,3) = List(1,2,3).::(0) = List(0,1,2,3) 從這里可以看出操作::其實(shí)是右邊List的操作符画侣,而非左邊Int類型的操作符
5.util包
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.
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
Array
長度固定
元素可變
確定長度冰悠,后賦值;
List
長度固定
元素不可變
Tuple
長度固定
元素不可變
常用于有多個返回值的函數(shù);或者多個變量的同時定義
Scala2.8中配乱,3者的元素都可以混合不同的類型(轉(zhuǎn)化為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.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") //相當(dāng)于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)之后跟:_*的依據(jù)
Array對應(yīng)的可變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)
元素合并進(jìn)List用::
val list2 = "a"::"b"::"c"::Nil // Nil是必須的
val list3 = "begin" :: list2 // list2不變忿檩,只能加在頭尉尾,不能加在尾
多個List合并用++,也可以用:::(不如++)
val list4 = list2++"end"++Nil
val list4 = list2:::"end" :: Nil //相當(dāng)于list2 ::: List("end")
當(dāng)import java.util._之后會產(chǎn)生沖突燥透,需要指明包
scala.List(1,2,3)
List對應(yīng)的可變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的隨機(jī)存取效率而引入的新集合類型(而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擴(kuò)展肢藐、updated之后是新生成的vector故河,原vector保持immutable。這點(diǎn)和List類似吆豹。
Seq的缺省實(shí)現(xiàn)是List:
Seq(1,2,3) // List(1, 2, 3)
IndexSeq的缺省實(shí)現(xiàn)是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和序列轉(zhuǎn)換:
1 to 5 toList
相當(dāng)與:
List(1 to 5:_*)
或者:
Vector(1 to 5: _*) // Vector(1,2,3,4,5)
5.2.1.6Stack Queue (List類的sibling)
先進(jìn)后出的堆棧:
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)
對應(yīng)的可變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)
先進(jìn)先出的隊列:
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)
對應(yīng)的可變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相當(dāng)于lazy List抑胎,避免在中間過程中生成不必要的集合。
定義生成:
val st = 1#::2#::3#::Stream.empty // Stream(1, ?)
例子:fib數(shù)列的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數(shù)列的前后項比值趨于黃金分割:
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,但很慢垢啼,需要大量內(nèi)存
Stream.range(1,50000000).filter(_%13==0)(1) // 26筷频,很快,只計算最終結(jié)果需要的內(nèi)容
注意:
第一個版本在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))都伪,碰到不符合就結(jié)束
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
返回序列中符合條件的第一個陨晶。
例子:查找整數(shù)的第一個因子(最小因子猬仁、質(zhì)數(shù))
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中的重復(fù)元素)
def uniq[T](l:List[T]) = l.distinct
uniq(List(1,2,3,2,1)) // List(1,2,3)
5.2.2.9flatMap
flatMap的作用:把多層次的數(shù)據(jù)結(jié)構(gòu)“平面化”,并去除空元素(如None)先誉。
可用于:得到xml等樹形結(jié)構(gòu)的所有節(jié)點(diǎn)名稱湿刽,去除None等
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,結(jié)果就是:
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結(jié)合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))
截取一部分,相當(dāng)于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
滿足條件的元素數(shù)目:
例如1000內(nèi)質(zhì)數(shù)的個數(shù):
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的數(shù)據(jù)結(jié)構(gòu)诈闺,使用updated返回一個新的copy:
val v1 = List(1,2,3,4)
v1.updated(3,10) // List(1, 2, 3,10), v1還是List(1, 2, 3,4)
對于可變的數(shù)據(jù)結(jié)構(gòu),直接更改:
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)
相當(dāng)于:
(1 to 5 reverse) map (10*)
5.2.2.15contains startsWith endWith
1 to 5contains3 // true,后一個參數(shù)是1個元素
1 to 5containsSlice(2 to 4) // true,后一個參數(shù)是1個集合
(1 to 5)startsWith(1 to 3) // true后一個參數(shù)是1個集合
(1 to 5)endsWith(4 to 5)
(List(1,2,3)correspondsList(4,5,6)) (_<_)// true雅镊,長度相同且每個對應(yīng)項符合判斷條件
5.2.2.16集合運(yùn)算
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)
//相當(dāng)于
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
統(tǒng)一使用()刃滓,而不是[]仁烹,()就是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,相當(dāng)于a.apply(0)
a(0)=10 // Array(10, 200, 300)注盈,相當(dāng)于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"
在某類型的集合對象上調(diào)用view方法僚饭,得到相同類型的集合震叮,但所有的transform函數(shù)都是lazy的,從該view返回調(diào)用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,相當(dāng)于:
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集合間的轉(zhuǎn)換(scalaj)
方案一:Java的List很容易通過List.toArray轉(zhuǎn)換到Array偿乖,和Scala中的Array是等價的击罪,可使用map、filter等贪薪。
方案二:使用第三方的scalaj擴(kuò)展包(需自行下載設(shè)置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類型
轉(zhuǎn)換方法
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類型
轉(zhuǎn)換方法
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]
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有“拉拉鏈”的意思画切,就是把兩排鏈扣完全對應(yīng)扣合在一起竣稽,非常形象。
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._后發(fā)生沖突霍弹,可指明: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)應(yīng)該被回收
另一種更新方式:
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))
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))
使用Java的HashMap:
val m1:java.util.Map[Int, String] = new java.util.HashMap
上面說過,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)
也可以進(jìn)行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)
相當(dāng)于:
map.values.toList
結(jié)合Map和Tuple本鸣,很容易實(shí)現(xiàn)一個key對應(yīng)的value是組合值的數(shù)據(jù)結(jié)構(gòu):
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))
注:BitSet(collection.immutable.BitSet)和Set類似,但操作更快
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)
運(yùn)算
例子
交集
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)
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())
Iterator不屬于集合類型硅蹦,只是逐個存取集合中元素的方法:
val it = Iterator(1,3,5,7) // Iterator[Int] = non-empty iterator
it foreach println // 1 3 5 7
it foreach println //無輸出
三種常用的使用模式:
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)
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也不可用了
Scala2.9+引入:
(1 to 10).parforeach println
多運(yùn)行幾次窒升,注意打印順序會有不同