当前位置: 首页>编程语言>正文

scala

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

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

  • 基本集合类 常用的集合类型
  • 层级关系 集合类的抽象关系
  • 集合方法
  • 可变性
  • Java 集合类也可直接使用

 

基本集合类

List

标准的linked list。

scala> List(          1          ,           2          ,           3          )         


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



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

scala>           1          ::           2          ::           3          :: Nil         


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




参考 API文档

 

Set

Set里不包含重复元素

scala> Set(          1          ,           1          ,           2          )         


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




参考 API文档

 

Seq

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

scala> Seq(          1          ,           1          ,           2          )         


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



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

参考 API文档

 

Map

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

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

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

def head : A         


          def tail : Traversable[A]



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

def map [B] (f: (A) => B) : CC[B]上面的代码返回一个集合,里面的每一个元素都通过函数f进行了转换。def foreachU: Unit对一个集合里的每一个元素都执行函数fdef 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]]

转换:

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

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转换成一个数组,然后得到一个键值对数组。

scala> Map(          1          ->           2          ).toArray         


          res41: Array[(Int, Int)] = Array((          1          ,          2          ))



Iterable

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

def iterator: Iterator[A]



Iterator提供了什么操作呢?

def hasNext(): Boolean         


          def next(): A




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

 

Set

def contains(key: A): Boolean         


          def +(elem: A): Set[A]         


          def -(elem: A): Set[A]




 

Map

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


scala> Map(          "a"          ->           1          ,           "b"          ->           2          )         


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



或者按照下面的方式:

scala> Map((          "a"          ,           2          ), (          "b"          ,           2          ))         


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




题外话

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

scala>           "a"          ->           2         


                    


          res0: (java.lang.String, Int) = (a,          2          )



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

scala>           "a"          .->(          2          )         


                    


          res1: (java.lang.String, Int) = (a,          2          )



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

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 API, HashMap API

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

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

scala> IndexedSeq(          1          ,           2          ,           3          )         


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




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


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


          1         


          2         


          3



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

scala> (          1          to           3          ).map { i => i }         


          res0: scala.collection.immutable.IndexedSeq[Int] = Vector(          1          ,           2          ,           3          )




默认实现

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

scala> Iterable(          1          ,           2          )         


                    


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



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

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

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

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 API, ArrayBuffer API

LinkedList和DoubleLinkedList LinkedList API, DoubleLinkedList API

PriorityQueue API doc

Stack和ArrayStack Stack API, ArrayStack API

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

 

和Java进行交互

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

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)



双向转换:

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



 

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

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


https://www.xamrdz.com/lan/54j1924539.html

相关文章: