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

1.数组Array

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

  def test() = {
val array1 = new Array[Int]()
array1() =
println(array1())
val array2 = Array(, , , , )
println(array2())
}

上面的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(,,)
println(x.getClass)
println(x()) val y = Range(, )
println(y)
}

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

class scala.collection.immutable.Vector

Range(, , , )

而作为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(,,)
val b = Set(,,)
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" -> , "Tracy" -> , "Lily" -> ) //不可变
// 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", ) // 因为是可变集合,所以可以put
map.put("Tracy", )
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() //后面添加元素
arrayBuffer.append()
arrayBuffer += //后面添加元素
+=: 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(, , )
TestForScala.printCollection(raw)
}

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

Scala集合类详解的更多相关文章

  1. Scala 入门详解

    Scala 入门详解 基本语法 Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的 Scala 程序是对象的集合,通过调用彼此的方法来实现消息传递.类,对象,方法,实例变 ...

  2. Java 集合类详解(含类图)

    0.参考文献 此图中蓝色为抽象类.深红色表示接口(Arrays除外).绿色表示具体容器类 1.java集合类图 1.1 1.2 上述类图中,实线边框的是实现类,比如ArrayList,LinkedLi ...

  3. Java: 集合类详解

    0.参考文献 http://blog.csdn.net/liulin_good/article/details/6213815 1.java集合类图 1.1 1.2 上述类图中,实线边框的是实现类,比 ...

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

    Scala是什么? Scala是以实现scaleable language为初衷设计出来的一门语言.官方中,称它是object-oriented language和functional languag ...

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

    http://www.artima.com/scalazine/articles/pattern_matching.html这篇文章是odersky谈scala中的模式匹配的一段对话,我做了部分片段翻 ...

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

    在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的.http://lampwww.epfl.ch/~emir/written/Matc ...

  7. Java 集合类详解

    集合类说明及区别 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └W ...

  8. Scala入门详解

    object作为Scala中的一个关键字,相当于Java中的public static class这样的一个修饰符,也就说object中的成员都是静态的! 所以我们在这个例子中的main方法是静态的, ...

  9. Java常用集合类详解

    在Java中有一套设计优良的接口和类组成了Java集合框架,使程序员操作成批的数据或对象元素极为方便.所有的Java集合都在java.util包中. 在编写程序的过程中,使用到集合类,要根据不同的需求 ...

随机推荐

  1. Java EE发展史

    前言 最近的这段时间一直在学习Java EE,刚刚完成了从0到1的蜕变,所以顺便整理一下我所了解到的Java EE,给刚入门学习的新人一些头绪,而所谓“启示录”,就是这个意思. 一.Java EE是什 ...

  2. System.Web.Mvc.AJAX缺少程序集引用

    今天在构建新项目的时候,出现这个错误,实际上这个出现过很多次了,但是每次都忘记之前怎么解决的,之前博客也不记得写过没有...

  3. Android设计和开发系列第二篇:Action Bar(Design)

    Action Bar The action bar is a dedicated piece of real estate at the top of each screen that is gene ...

  4. Undeclared identifier:XXX

    未识别错误,是因拼写错误或找不到定义文件. 下面列举一些类型和函数用到的单元. _Stream ADODB_TLB akTop, akLeft, akRight, akBottom Controls ...

  5. cookie设置在特定时间点过期的方法

    假设需求为:在当天晚上0:00过期. 方法: 得到当天晚上0:00这个时间点的一个时间. function getNextDate(){        var d = new Date(),      ...

  6. explain 和 desc 详解

    MySQL性能分析 1.使用explain语句去查看分析结果 如explain select * from test1 where id=1;会出现:id  selecttype  table  ty ...

  7. time_t到.NET DateTime的转换

    time函数返回的time_t是一个utc时间且相对于1970年1月1日的total seconds,转换到DateTime只需以相同的方式转换回去即可. C/C++ auto t = time(); ...

  8. 搭建IPv4专有网络

    搭建IPv4专有网络 版权归属:阿里云网站   本教程将指引您搭建一个具有IPv4地址块的专有网络,并为专有网络中的ECS实例绑定一个弹性公网IP(EIP)进行公网访问. 步骤一:创建专有网络和交换机 ...

  9. Xcode快速排错

    EXTENDS:http://blog.csdn.net/guo_hongjun1611/article/details/8063009 1,模拟器运行完全没问题,真机运行失败. 有时候我们在模拟器上 ...

  10. Swift 使用 LLDB 调试命令

    swift 和 oc 的语法不一样: Xcode 调试技巧之 Swift 篇 打印和赋值,观察数值变量和view对象属性 p指令可打印其对象类型.内存地址以及该对象的值等具体信息, po指令则是打印其 ...