Scala具体解释---------数组、元组、映射
一、数组
1、定长数组
声明数组的两种形式:
声明指定长度的数组 val 数组名= new Array[类型](数组长度)
Scala声明数组时。须要带有Array类名,且使用 () 来指明长度或提供初始值序列。
在JVM中。Scala的Array以Java数组的方式实现。如arr在JVM中的类型相应java.lang.String[]。charArr相应char[]。
2、变长数组
ArrayBuffer,全称scala.collection.mutable.ArrayBuffer,类似于Java中的ArrayList和C++中的vector,是长度可变数组类型的结构,称为数组缓冲。
通过:val 名 = ArrayBuffer[类型]() 来声明。声明ArrayBuffer时须要指明类型。
通过 += 操作符来加入元素或序列,++= 操作符来拼接数组。
【在ArrayBuffer的尾端加入或删除元素是一个高效的操作。】 ArrayBuffer还支持在指定位置插入、删除元素。
ArrayBuffer到数组的转换: toArray方法
3、数组遍历
通过for循环来遍历数组
指定遍历数组的步长——通过until(上界, 步长)
通过reverse函数逆序遍历数组:
4、能够通过 for循环+yield 来获得新的数组或ArrayBuffer
通过for+yield操作数组或ArrayBuffer之后将得到新的数组或ArrayBuffer。
5、操作数组/数组缓冲经常使用函数
求和、求最大最小值、数组排序。通过sorted函数对数组或ArrayBuffer排序时。返回的是一个新的数组或ArrayBuffer,原有的不变。
能够直接对数组调用排序算法。可是不能对ArrayBuffer排序。
quickSort是直接改动原数组,而sorted方法是返回新数组。
6、多维数组
Scala中的多维数组同Java中一样,多维数组都是数组的数组。
通过 Array.ofDim[类型](维度1, 维度2, 维度3,....)来声明多维数组。如声明二维数组;
从二维数组的初始化中,我们能够看到,多维数组在Scala中也是数组的数组。
通过 Array[ Array[Int]](维度1) 来声明数组,能够声明不规则数组;
多维数组是数组的数组,依照这样的性质来声明多维数组,如样例中的二维数组,声明时,须要指定最外围的数组大小。
【注:能够通过scala.collection.JavaConversions包中隐式转换方法来实现Scala容器类与Java中类的转换。】
二、映射
1、映射构造
对偶,即名值对。能够通过 -> 操作符来定义对偶, 名->值 运算的结果是( 名, 值 )。
也能够声明对偶形式的变量:
映射是由对偶构成的,映射是对偶的集合。
声明不可变映射。直接使用Map来声明时。默认是不可变映射类型。
【注: 不可变映射维持元素插入顺序。
】
声明可变映射(scala.collection.mutable.Map)
【注:放入可变映射中的值并未依照放入顺序来排序的。】
通过for循环来改动可变Map中的值;
【注:映射可变、不可变指的是整个映射是否可变。包含元素值、映射中元素个数、元素次序等。】
声明空映射直接通过 new Map[类型1, 类型2]() 来定义映射会报错,由于Map是抽象的。无法实例化。
定义空映射时,须要指定映射的实现类,通过new来定义;
分别定义不可变映射与可变映射。注。直接使用 new HashMap定义时会报错。
2、映射经常使用操作
推断映射中是否含有某个键: map.contains(键值)
通过映射的 keySet 方法能够获得映射的由键值构成的集合。通过 values 方法能够获得映射的值集合的Interable对象,应用于循环中。
Scala的keySet / values 方法类似于Java中的映射方法。
3、Scala中映射的底层实现要么基于哈希表,要么基于平衡树,当中基于平衡树的映射内部是有序的。
Scala眼下基于平衡树的映射仅仅提供了不可变版本号。
【注:构建可变有序映射可借助Java的TreeMap。
】
4、可变映射中,若穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq5ub2ozqyz1tSqy9iy5cjry7PQ8rXE07PJ5L/Jzai5/UxpbmtlZEhhc2hNYXChozwvcD4KPHA+NaGizai5/XNjYWxhLmNvbGxlY3Rpb24uSmF2YUNvbnZlcnNpb25zLm1hcEFzU2NhbGFNYXC/yb2rSmF2YbXETWFw16q7u86qU2NhbGHA4NDNtcRNYXCju82ouf1zY2FsYS5jb2xsZWN0aW9uLkphdmFDb252ZXJzaW9ucy5tYXBBc0phdmFNYXC/yb2rU2NhbGG1xNOzyeTXqru7zqpKYXZhwODQzbXE07PJ5KGjPC9wPgo8cD42oaJ0b01hcLe9t6g8L3A+CjxwPqGhoaHKudPDdG9NYXC3vbeov8m9q7bUxbzX6bPJtcS8r7rP16q7r86q07PJ5KGjPC9wPgo8cD6hoaGhPGltZyBzcmM9"http://www.it165.net/uploadfile/files/2014/0920/20140920190600125.png" alt="\" />
三、元组
1、元组是不同类型的值的聚集;对偶是最简单的元组。
2、元组表示
通过将不同的值用小括号括起来,即表示元组。
上例中元组的类型就是 (Int, Double, Char, String) 。元组中能够存放不同类型的值。
3、元组訪问
元组中的元素称为组元。能够通过 _1、 _2 、_3 的形式来訪问相应下标的组元。
【注:元组中组元下标从1開始。】
通过模式匹配来訪问元组中的值
忽略不需穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq1xNa1PC9zdHJvbmc+oaPU2sSjyr3GpcXkyrGjrM2ouf0gXyCjqM3yxNzGpcXkt/ujqcC0zqqyu9Do0qq78cih1rW1xNfp1KrVvM67o6zDv7j2IF8gvfa/ydLUzqrSu7j21+nUqtW8zruhozwvcD4KPHA+oaGhoTxpbWcgc3JjPQ=="http://www.it165.net/uploadfile/files/2014/0920/20140920190600129.png" alt="\" />
4、元组可用于函数返回多个值的情形
上例中,函数定义返回值类型为元组 (Int, String);
下面是对集合的简述:
Scala有一组丰富的集合库。
集合是对事物的容器。
这些容器可被測序。线性集像List, Tuple, Option, Map等集合的项目可具有元素的随意数量或有界到零个或一个元素(比如,Option)。
集合可能是严格或懒惰。
懒集合有可能不消耗内存,直到他们被訪问。就像范围元素。此外,集合能够是可变的(引用的内容能够更改)或不变(一个引用的东西指从未改变)。须要注意的是不可变的集合可能包括可变项。
对于一些问题,可变集合更好地工作,并为不可变集合更好地工作。假设有疑问,最好是先从一个不变的集合。假设须要可变进行更改。
本章给出最经常使用的集合类型对这些集合的信息和使用最频繁的操作。
SN | 集合使用说明 |
---|---|
1 |
Scala Lists Scala的List[T]是T类型的链表 |
2 |
Scala Sets 集是同样类型的配对的不同元素的集合。 |
3 |
Scala Maps 映射是键/值对的集合。不论什么值能够依据它的键进行检索。 |
4 |
Scala Tuples 不像数组或列表,元组能够容纳不同类型的对象。 |
5 |
Scala Options Option[T] 提供了一种容器,用于给定类型的零个或一个元素。 |
6 |
Scala Iterators 迭代不是集合,而是一种由一个訪问的集合之中的一个的元素。 |
演示样例:以下的代码片段是一个简单的样例来定义全部上述集合类型:
// Define List of integers. val x = List(1,2,3,4) // Define a set. var x = Set(1,3,5,7) // Define a map. val x = Map("one" -> 1, "two" -> 2, "three" -> 3) // Create a tuple of two elements. val x = (10, "Scala") // Define an option val x:Option[Int] = Some(5)
映射和元组 |
摘要:
一个经典的程序猿名言是:"假设仅仅能有一种数据结构。那就用哈希表吧"。哈希表或者更笼统地说映射,是最灵活多变的数据结构之中的一个。
映射是键/值对偶的集合。Scala有一个通用的叫法:元组,即n个对象的聚集。并不一定要同样类型的。
对偶只是是一个 n=2的元组,元组对于那种须要将两个或很多其它值聚集在一起时特别实用。本篇的要点包含:
01. Scala有十分易用的语法来创建、查询和遍历映射。
02. 你须要从可变的和不可变的映射中做出选择。
03. 默认情况下,你得到的是一个哈希映射。只是你也能够指明要树形映射。
04. 你能够非常easy地在Scala映射和Java映射之间来回切换。
05. 元组能够用来聚集值。
构造映射 |
不可变映射
我们能够这样构造一个映射:
val scores = Map ("Alice"-> 10, "Bob"->3, "Cindy"->8)
上述代码构造出一个不可变的Map[String,Int],其值不能被改变。
可变映射
假设你想要一个可变映射,则用
val scores = scala.collection.mutable.Map("Alice"-> 10, "Bob"->3, "Cindy"->8)
假设想从—个空的映射開始,你须要选定一个映射实现并给出类型參数:
val scores = new scala.collection.mutable.HashMap [String, Int]
在Scala中,映射是对偶的集合。对偶简单地说就是两个值构成的组,这两个值并不一定是同一个类型的,比方("Alice",10)
操作符创建对偶
操作符用来创建对偶:
"Alice"->10
上述代码产出的值是:
("Alice", 10)
全然也能够用以下这样的方式来定义映射:
val scores=Map ( ("Alice", 10), ("Bob", 3), ("Cindy", 8) )
仅仅只是->操作符看上去比圆括号更易读那么一点,也更加符合大家对映射的直观感觉:映射这样的数据结构是一种将键映射到值的函数。差别在于通常的函数计算值,而映射仅仅是做查询。
获取映射中的值 |
在Scala中,函数和映射之间的相似性尤为明显,由于你将使用()表示法来查找某个键相应的值:
val bobsScore = scores ("Bob") //类似于Java中的scores.get ("Bob")
假设映射并不包括请求中使用的键,则会抛出异常。要检查映射中是否有某个指定的键,能够用contains方法:
val bobsScore = if (scores.contains ("Bob")) scores("Bob") else 0
因为这种组合调用十分普遍。下面是一个快捷写法:
val bobsScore = scores.getOrElse("Bob", 0) // 假设映射包括键"Bob",返回相应的值;否则。返回0
最后。映射.get(键)这种调用返回一个Option对象,要么是Some(键相应的值)。要么是None
更新键值 |
更新可变映射
在可变映射中,你能够更新某个映射的值,或者加入一个新的映射关系,做法是在=号的左側使用():
scores ("Bob") = 10 // 更新键"Bob"相应的值
scores ("Fred")=7 // 添加新的键/值对偶到scores
或者。你也能够用+=操作来加入多个关系:
scores+= ("Bob"-> 10, "Fred"->7)
要移除某个键和相应的值,使用-=操作符:
scores -= "Alice"
不可变映射
尽管不能更新一个不可变的映射,但你能够做一些相同实用的操作,即获取一个包括所须要的更新的新映射:
val newScores = scores+ ("Bob"->10,"Fred"->7) // 更新过的新映射
newScores映射包括了与scores同样的映射关系。此外"Bob"被更新。"Fred"被加入了进来
除了把结果作为新值保存外,你也能够更新Var变量:
var scores = …
scores = scores+ ("Bob"->10, "Fred"->7)
同理,要从不可变映射中移除某个键,你能够用一操作符来获取一个新的去掉该键的映射:
scores = scores - "Alice"
你可能会认为这样不停地创建新映射效率非常低,只是事实并不是如此。老的和新的映射共享大部分结构。这样做之所以可行,是由于它们是不可变的。
迭代映射 |
例如以下这段超简单的循环就可以遍历映射中全部的键/值对偶:
for ((k,v) <- 映射) 处理k和v
这里的"魔法"是你能够在Scala的for循环中使用模式匹配。这样一来,不须要冗杂的方法调用。你就能够得到每个对偶的键和值
假设出于某种原因,你仅仅须要訪问键或值,像Java一样,则能够用keySet和values方法。values方法返回—个Iterable,你能够在for循环其中使用这个Iterable
scores.keySet // 一个类似Set("Bob"。"Cindy"。"Fred","Alice")这种集合
for ( v <- scores.values) printlnI(v) // 将打印10 8 7 10或其它排列组合
要反转一个映射,即交换键和值的位置。能够用:
for ( (k,v) <- 映射) yield (v.k)
已排序映射 |
在操作映射时。你须要选定一个实现:一个哈希表或者一个平衡树。默认情况下,Scala给的是哈希表。
因为对使用的键没有非常好的哈希函数。或者须要顺序地訪问全部的键。因此,你可能会想要一个树形映射。
要得到一个不可变的树形映射而不是哈希映射的话,能够用:
val scores = scala.collections.immutable.SortedMap("Alice"->10。"Fred"->7, "Bob"->3。"Cindy"->8)
非常可惜,Scala( 2.9)并没有可变的树形映射。假设那是你要的,最接近的选择是使用Java的TreeMap。须要注意的是:假设要按插入顺序訪问全部键。使用LinkedHashMap,比如:
val months = scala.collection.mutable.LinkedHashMap("January" -> 1,"February" -> 2。 "March" -> 3。 …)
与Java互操作 |
Java到Scala
假设你通过Java方法调用得到了一个Java映射。你可能想要把它转换成一个Scala映射。以便使用更便捷的Scala映射API。这对于须要操作Scala。并未提供的可变树形映射的情况也非常实用。仅仅须要添加例如以下引入语句:
import scala.collection.JavaConversions .mapAsScalaMap
然后通过指定Scala映射类型来触发转换:
val scores:scala.collection.mutable.Map[String, Int]=new java.util.TreeMap[String, Int]
除此之外,你还能够得到从java.util.Properties到Map[String。String]的转换:
import scala.collection.JavaConversions.propertiesAsScalaMap
val props:Scala.collection.Map[String, String] = System.getProperties()
Scala到Java
反过来讲,要把Scala映射传递给预期Java映射的方法,提供相反的隐式转换就可以
比如:
import scala.collection.JavaConversions.mapAsjavaMap
import java.awt.font.TextAttribute. _ // 引入以下的映射会用到的键
val attrs = Map ( FAMILY -> "Serif", SIZE -> 12 ) // Scala映射
val font=new java.awt.Font (attrs) // 该方法预期一个Java映射
元组 |
元组定义
映射是键/值对偶的集合。对偶足元组( tuple)的最简单形态,元组是不同类型的值的聚集。
元组的值是通过将单个的值包括在圆括号里构成的。比如:
(1, 3.14, "Fred")
是一个元组。类型为:
Tuple3 [Int, Double, java.lang.String]
类型定义也能够写为:
(Int, Double, java,lang.String)
假设你有一个元组。比方:
val t = (1,3.14, "Fred")
你就能够用方法_1、_2、_3訪问其组元,比方:
val second = t._2 // 将second设为3.14
须要注意的是:和数组或字符串中的位置不同,元组的各组元从1開始,而不是0。
你能够把t._2写为t _2。即用空格而不是句点。但不能写成t_2
获取元组
通常,使用模式匹配来获取元组的组元。比如:
val (first,second,third)=t //将first设为1,second设为3.14.third设为"Fred"
假设并非全部的部件都须要。那么能够在不须要的部件位置上使用_:
val (first, second, _ ) = t
元组能够用于函数须要返回不止一个值的情况。举例来说,StringOps的partition方法返回的是一对字符串,分别包括了满足某个条件和不满足该条件的字符:
"New York".partition ( _.isUpper) //输出对偶( "NY"。"ew ork")
拉链操作 |
使用元组的原因之中的一个是把多个值绑在一起。以便它们可以被一起处理。这通常可以用zip方法来完毕。
举例来说。以下的代码:
val symbols = Array ("<"。"-",">")
val counts = Array (2, 10, 2)
val pairs = symbols.zip(counts)
输出对偶的数组:
Array ( ("<",2),("-",10), (">",2) )
然后这些对偶就能够被一起处理:
for ( (s,n) <- pairs ) Console.print(s*n) // 会打印<<---------->>
须要注意的是:用toMap方法能够将对偶的集合转换成映射。假设你有一个键的集合,以及一个与之平行相应的值的集合,那么你就能够用拉链操作将它们组合成一个映射:keys.zip(values) .toMap