Scala集合类详解

对scala中的集合类虽然有使用,但是一直处于一知半解的状态。尤其是与java中各种集合类的混合使用,虽然用过很多次,但是一直也没有做比较深入的了解与分析。正好趁着最近项目的需要,加上稍微有点时间,特意多花了一点时间对scala中的集合类做个详细的总结。

1.数组Array

在说集合类之前,先看看scala中的数组。与Java中不同的是,Scala中没有数组这一种类型。在Scala中,Array类的功能就与数组类似。 
与所有数组一样,Array的长度不可变,里面的数据可以按索引位置访问。

  def test() = {
    val array1 = new Array[Int](5)
    array1(1) = 1
    println(array1(1))
    val array2 = Array(0, 1, 2, 3, 4)
    println(array2(3))
  }

上面的demo就演示了Array的简单用法。

2.集合类的大致结构

盗用网上的一张图,scala中集合类的大体框架如下图所示。

特意查了下scala的源码,贴上几张图,可以对应到上面的这幅继承关系图。

根据图以及源码可以很清晰地看出scala中的集合类可以分为三大类: 
1.Seq,是一组有序的元素。 
2.Set,是一组没有重复元素的集合。 
3.Map,是一组k-v对。

3.Seq分析

Seq主要由两部分组成:IndexedSeq与LinearSeq。现在我们简单看下这两种类型。

首先看IndexedSeq,很容易看出来这种类型的主要访问方式是通过索引,默认的实现方式为vector。

 def test() = {
    val x = IndexedSeq(1,2,3)
    println(x.getClass)
    println(x(0))

    val y = Range(1, 5)
    println(y)
  }

将以上函数运行起来以后,输出如下:

class scala.collection.immutable.Vector
1
Range(1, 2, 3, 4)

而作为LinearSeq,主要的区别在于其被分为头与尾两部分。其中,头是容器内的第一个元素,尾是除了头元素以外剩余的其他所有元素。LinearSeq默认的实现是List。

 def test() = {
    val x = collection.immutable.LinearSeq("a", "b", "c")
    val head = x.head
    println(s"head is: $head")

    val y = x.tail
    println(s"tail of y is: $y")
  }

将上面的代码运行起来以后,得到的结果如下:

head is: a
tail of y is: List(b, c)

4.Set

与其他任何一种编程语言一样,Scala中的Set集合类具有如下特点: 
1.不存在有重复的元素。 
2.集合中的元素是无序的。换句话说,不能以索引的方式访问集合中的元素。 
3.判断某一个元素在集合中比Seq类型的集合要快。

Scala中的集合分为可变与不可变两种,对于Set类型自然也是如此。先来看看示例代码:

 def test() = {
    val x = immutable.HashSet[String]("a","c","b")
    //x.add("d")无法使用,因为是不可变集合,没有add方法。
    val y = x + "d" + "f"  // 增加新的元素,生成一个新的集合
    val z = y - "a"  // 删除一个元素,生成一个新的集合
    val a = Set(1,2,3)
    val b = Set(1,4,5)
    val c = a ++ b  // 生成一个新的集合,增加集合
    val d = a -- b  // 生成一个新的集合,去除集合
    val e = a & b // 与操作
    val f = a | b // 或操作
  }

因为上面代码里的集合类型都是不可变类型,所以所有语句结果其实都是生成一个新的集合。

 def test() = {
    val x = new mutable.HashSet[String]()
    x += "a"  // 添加一个新的元素。注意此时没有生成一个新的集合
    x.add("d") //因为是可变集合,所以有add方法
    x ++= Set("b", "c")  // 添加一个新的集合
    x.foreach(each => println(each))
    x -= "b"  // 删除一个元素
    println()
    x.foreach(each => println(each))
    println()
    val flag = x.contains("a") // 是否包含元素
    println(flag)
  }

将上面这段代码运行起来以后,得到的结果如下:

c
d
a
b

c
d
a

true

5.Map

Map这种数据结构是日常开发中使用非常频繁的一种数据结构。Map作为一个存储键值对的容器(key-value),其中key值必须是唯一的。 默认情况下,我们可以通过Map直接创建一个不可变的Map容器对象,这时候容器中的内容是不能改变的。示例代码如下。

 def test() = {
    val peoples = Map("john" -> 19, "Tracy" -> 18, "Lily" -> 20) //不可变
    // people.put("lucy",15) 会出错,因为是不可变集合。
    //遍历方式1
    for(p <- peoples) {
      print(p + "  ") // (john,19)  (Tracy,18)  (Lily,20)
    }
    //遍历方式2
    peoples.foreach(x => {val (k, v) = x; print(k + ":" + v + "  ")}) //john:19  Tracy:18  Lily:20
    //遍历方式3
    peoples.foreach ({ case(k, v) => print(s"key: $k, value: $v  ")})
    //key: john, value: 19  key: Tracy, value: 18  key: Lily, value: 20
  }

上面代码中的hashMap是不可变类型。 
如果要使用可变类型的map,可以使用mutable包中的map相关类。

 def test() = {
    val map = new mutable.HashMap[String, Int]()
    map.put("john", 19) // 因为是可变集合,所以可以put
    map.put("Tracy", 18)
    map.contains("Lily") //false
    val res = getSome(map.get("john"))
    println(res) //Some(19)
  }

  def getSome(x:Option[Int]) : Any = {
    x match {
      case Some(s) => s
      case None => "None"
    }
  }

6.可变数组ArrayBuffer

特意将ArrayBuffer单独拎出来,是因为ArrayBuffer类似于Java中的ArrayList。而ArrayList在Java中是用得非常多的一种集合类。 
ArrayBuffer与ArrayList不一样的地方在于,ArrayBuffer的长度是可变的。与Array一样,元素有先后之分,可以重复,可以随机访问,但是插入的效率不高。

def test() = {
    val arrayBuffer = new mutable.ArrayBuffer[Int]()
    arrayBuffer.append(1)  //后面添加元素
    arrayBuffer.append(2)
    arrayBuffer += 3  //后面添加元素
    4 +=: arrayBuffer  //前面添加元素
  }

7.java与scala集合的相互转换

scala最大的优势之一就是可以使用JDK上面的海量类库。实际项目中,经常需要在java集合类与scala集合类之间做转化。具体的转换对应关系如下:

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
java.util.Properties => scala.collection.mutable.Map[String, String]

在使用这些转换的时候,只需要scala文件中引入scala.collection.JavaConversions._ 即可。

一般比较多件的场景是在scala中调用java方法。如前面所讲,jdk的类库太丰富了,在scala中会经常有调用java方法的需求。给个简单的例子: 
假设有如下java代码:

public class TestForScala {

    public static <T> void printCollection(List<T> list) {
        for(T t: list) {
            System.out.println(t);
        }
    }
}

我们想在scala代码中调用TestForScala类中的printCollection方法。可以这么写:

 def test() = {
    val raw = Vector(1, 2, 3)
    TestForScala.printCollection(raw)
  }

java方法中需要的参数是个List,参照我们前面的转换关系,scala.collection.Seq可以自动转化为java中的List,而Vector就是scala中Seq的实现,所以可以直接传入到printCollection方法中!

原文地址:https://www.cnblogs.com/itboys/p/9281197.html

时间: 2024-08-29 09:22:00

Scala集合类详解的相关文章

Java 集合类详解

1.java集合类图 1.1 1.2 上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等. 发现一个特点,上述所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法.它的一个

java基础学习——4、集合类详解

一.Java集合框架图 上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等. 发现一个特点,上述所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法. 它的一个子接口Lin

scala 模式匹配详解 3 模式匹配的核心功能是解构

http://www.artima.com/scalazine/articles/pattern_matching.html这篇文章是odersky谈scala中的模式匹配的一段对话,我做了部分片段翻译(不是连贯的): 模式可以嵌套,就像表达式嵌套,你可以定义深层的模式,通常一个模式看起来就像一个表达式.它基本上就是同一类事情.它看起来像一个复杂的对象树构造表达式,只是漏掉了new关键字.事实上在scala当你构造一个对象,你不需要new关键字然后你可以在一些地方用变量做站位符替代对象树上实际的

scala 模式匹配详解 2 scala里是怎么实现的?

在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的.http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf我引用了里面的一些描述. 在面向对象的程序中数据被组织为一级一级的类(class)面向对象语言在模式匹配方面的问题在于如何从外部探测这个层级. 有6种实现模式匹配的方法:1) 面向对象的分解 (decomposition)2) 访问器模式

Spark入门到精通--(第二节)Scala编程详解基础语法

Scala是什么? Scala是以实现scaleable language为初衷设计出来的一门语言.官方中,称它是object-oriented language和functional language的混合式语言. Scala可以和java程序无缝拼接,因为scala文件编译后也是成为.class文件,并且在JVM上运行. Spark是由Scala进行开发的. Scala安装? 这里就讲一下Scala在Centos上进行安装的过程,和安装JDK差不多. 官网下载Scala:http://www

Java集合类详解(转)

Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).JavaSDK不提供直接继承自Collection的类,javaSDK提供的类都是继承自Collection的"子接口"如List和Set. 所

Java集合类详解

集合类说明及区别Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些 Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Collection的类,J

Java集合排序及java集合类详解--(Collection, List, Set, Map)

1         集合框架 1.1         集合框架概述 1.1.1         容器简介 到目前为止,我们已经学习了如何创建多个不同的对象,定义了这些对象以后,我们就可以利用它们来做一些有意义的事情. 举例来说,假设要存储许多雇员,不同的雇员的区别仅在于雇员的身份证号.我们可以通过身份证号来顺序存储每个雇员,但是在内存中实现呢?是不是要准备足够的内存来存储1000个雇员,然后再将这些雇员逐一插入?如果已经插入了500条记录,这时需要插入一个身份证号较低的新雇员,该怎么办呢?是在内

scala collection详解

原帖:http://stackoverflow.com/questions/1722137/scala-2-8-collections-design-tutorial There's a 2.8 collection walk-through by Martin Odersky which should probably be your first reference. It has been supplemented as well with architectural notes, whic