Scala集合(二)

Scala提供了一系列的集合类的实现。同时,它对于集合类型也进行了一些抽象。这就使得你可以操作一个集合的Foo对象,而不用去关心这个集合是一个ListSet还是其他的什么。

这个网页提供了一个很好的方式来理解scala里的集合的默认实现,并且都链接到了相应的scaladoc。

 

基本集合类

List

标准的linked list。

1
2
scala> List( 1 , 2 , 3 )
res0: List[Int] = List( 1 , 2 , 3 )

你也可以像在函数式语言里一样把它们串接起来。

1
2
scala> 1 :: 2 :: 3 :: Nil
res1: List[Int] = List( 1 , 2 , 3 )

参考 API文档

 

Set

Set里不包含重复元素

1
2
scala> Set( 1 , 1 , 2 )
res2: scala.collection.immutable.Set[Int] = Set( 1 , 2 )

参考 API文档

 

Seq

Sequence都有一个预定义的顺序。

1
2
scala> Seq( 1 , 1 , 2 )
res3: Seq[Int] = List( 1 , 1 , 2 )

(注意返回的结果是一个List。Seq是一个trait;List是它的一个实现类。Seq对象是一个工厂对象,正如你所看到的,它会创建一个List。)

参考 API文档

 

Map

Map是保存键-值对的容器。

1
2
scala> Map( 'a' -> 1 , 'b' -> 2 )
res4: scala.collection.immutable.Map[Char,Int] = Map((a, 1 ), (b, 2 ))

参考 API文档

 

层级关系

上面的这些都是trait,在可变(mutable)包和不可变(immutable)包里都有对应的实现,同时也有其他特殊用途的实现。

 

Traversable

所有的集合都可遍历的。这个trait定义了标准函数组合器。这些组合器都是通过foreach这个方法来实现的,并且所有的集合都实现了这个方法。

参考 API文档

 

Iterable

这个trait有一个iterator()方法,它返回一个可以遍历所有元素的Iterator。 参考 API文档

 

Seq

一组有序的元素。

参考 API文档

 

Set

一组没有重复元素的集合。

参考 API文档

 

Map

键-值对。

参考 API文档

 

方法

Traversable

上面所有的方法在子类中都是可用的。参数和返回值可能会改变,因为子类可以覆盖它们。

1
2
def head : A
def tail : Traversable[A]

这里我们可以定义函数组合器。

def map [B] (f: (A) => B) : CC[B]

上面的代码返回一个集合,里面的每一个元素都通过函数f进行了转换。

def foreachU: Unit

对一个集合里的每一个元素都执行函数f

def find (p: (A) => Boolean) : Option[A]

它返回第一个符合断言函数的元素。

def filter (p: (A) => Boolean) : Traversable[A]

这个返回一个包含所有符合断言函数的元素的集合。

切分:

def partition (p: (A) ⇒ Boolean) : (Traversable[A], Traversable[A])

通过一个断言函数把一个集合拆成两份

def groupBy [K] (f: (A) => K) : Map[K, Traversable[A]]

转换:

有趣的是,集合之间可以相互进行转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
def toArray : Array[A]
def toArray [B >: A] (implicit arg0: ClassManifest[B]) : Array[B]
def toBuffer [B >: A] : Buffer[B]
def toIndexedSeq [B >: A] : IndexedSeq[B]
def toIterable : Iterable[A]
def toIterator : Iterator[A]
def toList : List[A]
def toMap [T, U] (implicit ev: <:<[A, (T, U)]) : Map[T, U]
def toSeq : Seq[A]
def toSet [B >: A] : Set[B]
def toStream : Stream[A]
def toString () : String
def toTraversable : Traversable[A]

我们可以把一个Map转换成一个数组,然后得到一个键值对数组。

1
2
scala> Map( 1 -> 2 ).toArray
res41: Array[(Int, Int)] = Array(( 1 , 2 ))

Iterable

这个接口给你提供了一个迭代器iterator。

1
def iterator: Iterator[A]

Iterator提供了什么操作呢?

1
2
def hasNext(): Boolean
def next(): A

这个是非常‘Java式’的用法。在Scala中,你很少会见到使用iterator的地方,大部分的时候你看到的都是函数组合器以及for循环语句。

 

Set

1
2
3
def contains(key: A): Boolean
def +(elem: A): Set[A]
def -(elem: A): Set[A]

 

Map

一序列键值对,提供按key进行查询的操作。 可以通过给apply()方法传入一个键值对的列表来创建Map:

1
2
scala> Map( "a" -> 1 , "b" -> 2 )
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a, 1 ), (b, 2 ))

或者按照下面的方式:

1
2
scala> Map(( "a" , 2 ), ( "b" , 2 ))
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a, 2 ), (b, 2 ))

题外话

->是什么呢?这是一个特殊的语法,它是一个返回值为元组的方法。

1
2
3
scala> "a" -> 2
 
res0: (java.lang.String, Int) = (a, 2 )

记住,它只是下面这种形式的语法糖:

1
2
3
scala> "a" .->( 2 )
 
res1: (java.lang.String, Int) = (a, 2 )

你也可以通过++来构造Map

1
2
scala> Map.empty ++ List(( "a" , 1 ), ( "b" , 2 ), ( "c" , 3 ))
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a, 1 ), (b, 2 ), (c, 3 ))

 

常用的集合子类

HashSet 和 HashMap 支持快速查找的最常用的集合类。HashSet APIHashMap API

TreeMap SortedMap的子类,它提供有序的访问方式。 TreeMap API

Vector 支持快速查找和更新 Vector API

1
2
scala> IndexedSeq( 1 , 2 , 3 )
res0: IndexedSeq[Int] = Vector( 1 , 2 , 3 )

Range 有序的通过空格分隔的Int序列。 在之前很多用来计数的for循环经常使用它。Range API

1
2
3
4
scala> for (i <- 1 to 3 ) { println(i) }
1
2
3

Range也支持标准的函数组合器。

1
2
scala> ( 1 to 3 ).map { i => i }
res0: scala.collection.immutable.IndexedSeq[Int] = Vector( 1 , 2 , 3 )

默认实现

在trait上使用apply方法会得到该trait的一个默认实现,例如,Iterable(1,2)返回一个List作为它的默认实现。

1
2
3
scala> Iterable( 1 , 2 )
 
res0: Iterable[Int] = List( 1 , 2 )

Seq也是这样的,我们之前见过

1
2
3
4
5
6
7
8
9
scala> Seq( 1 , 2 )
res3: Seq[Int] = List( 1 , 2 )
 
scala> Iterable( 1 , 2 )
res1: Iterable[Int] = List( 1 , 2 )
 
scala> Sequence( 1 , 2 )
warning: there were deprecation warnings; re-run with -deprecation for details
res2: Seq[Int] = List( 1 , 2 )

Set

1
2
scala> Set( 1 , 2 )
res31: scala.collection.immutable.Set[Int] = Set( 1 , 2 )

 

一些描述性的trait

IndexedSeq 支持对元素进行快速随机访问以及快速的length操作 API doc

LinearSeq 只对第一个和最后一个元素支持快速访问。 API doc

 

可变性 vs. 不可变性

不可变性

优点

  • 在多线程场景下不会被改变

缺点

  • 没有办法进行修改

Scala允许我们根据实际需求决定可变性,它鼓励我们只用不可变的对象,但是也不禁止我们使用具有可变性的对象。这个和var与val的场景非常相似。我们一开始都是使用val,当实际需要的时候会改成var。

 

可变集合

我们前面讨论的所有的类都是不可变的。我们现在来讨论一下常用的可变集合。

HashMap 定义了getOrElseUpdate+= HashMap API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
scala> val numbers = collection.mutable.Map( 1 -> 2 )
numbers: scala.collection.mutable.Map[Int,Int] = Map(( 1 , 2 ))
 
scala> numbers.get( 1 )
res0: Option[Int] = Some( 2 )
 
scala> numbers.getOrElseUpdate( 2 , 3 )
res54: Int = 3
 
scala> numbers
res55: scala.collection.mutable.Map[Int,Int] = Map(( 2 , 3 ), ( 1 , 2 ))
 
scala> numbers += ( 4 -> 1 )
res56: numbers.type = Map(( 2 , 3 ), ( 4 , 1 ), ( 1 , 2 ))

 

ListBuffer和ArrayBuffer 定义了+=操作符 ListBuffer APIArrayBuffer API

LinkedList和DoubleLinkedList LinkedList APIDoubleLinkedList API

PriorityQueue API doc

Stack和ArrayStack Stack APIArrayStack API

StringBuilder 有趣的是StringBuilder是竟然一个集合 API doc

 

和Java进行交互

你可以通过 JavaConverters 包在Java和Scala的集合类之间进行转换. 它给常用的Java集合提供了asScala方法,同时给常用的Scala集合提供了asJava方法。

1
2
3
4
5
import scala.collection.JavaConverters._
val sl = new scala.collection.mutable.ListBuffer[Int]
val jl : java.util.List[Int] = sl.asJava
val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
assert (sl eq sl2)

双向转换:

1
2
3
4
5
6
7
scala.collection.Iterable <=> java.lang.Iterable
scala.collection.Iterable <=> java.util.Collection
scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set <=> java.util.Set
scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap

 

另外,下面提供了一些单向的转换方法:

1
2
3
4
scala.collection.Seq => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set => java.util.Set
scala.collection.Map => java.util.Map
07-30 115
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值