放在第一行比较显眼:
Array和ArrayBuffer可变还是不可变是指的长度
Map的可变与不可变是指的Map中是值
Array数组
在Scala中,Array代表的含义与Java中类似,也是长度不可改变的数组。此外,由于Scala与Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上是Java数组。例如字符串数组在底层就是Java的String[],整数数组在底层就是Java的Int[]。
数组初始化后,长度就固定下来了,而且元素全部根据其类型初始化
scala> val a = new Array[Int](10)
a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
scala> a(1) = 3
scala> a(1)
res1: Int = 3
scala> val b = new Array[String](10)
b: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)
scala> b(1)="qw"
scala> b(1)
res4: String = qw
可以直接使用Array()创建数组,元素类型自动推断。
scala> val a = Array("Hello","Word")
a: Array[String] = Array(Hello, Word)
scala> a(0)
res5: String = Hello
scala> a(0) = "hi"
scala> a(0)
res7: String = hi
类型可以不同
scala> val a = Array("len",19)
a: Array[Any] = Array(len, 19)
ArrayBuffer
在Scala中,如果需要类似于Java中的ArrayList这种长度可变的集合类,则可以使用ArrayBuffer
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
// 使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer
scala> val c = ArrayBuffer[Int]()
c: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
// 使用+=操作符,可以添加一个元素,或者多个元素
// 这个语法必须要谨记在心!因为spark源码里大量使用了这种集合操作语法!
scala> c += 1
res13: c.type = ArrayBuffer(1)
scala> c += (2,3,4,5)
res15: c.type = ArrayBuffer(1, 2, 3, 4, 5)
使用++=操作符,可以添加其他集合中的所有元素
scala> c ++= Array(4,56,78,99,45)
res16: c.type = ArrayBuffer(1, 2, 3, 4, 5, 4, 56, 78, 99, 45)
使用trimEnd()函数,可以从尾部截断指定个数的元素
scala> c.trimEnd(5)
scala> c
res18: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)
使用insert()函数可以在指定位置插入元素, 但是这种操作效率很低,因为需要移动指定位置后的所有元素
insert函数第一个参数是要插入元素的索引,第二个参数是具体的值。
scala> c.insert(3,21)
scala> c
res24: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 21, 4, 5)
添加多个元素
scala> c.insert(3,98,87,76,65)
scala> c
res26: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 98, 87, 76, 65, 21, 4, 5)
remove函数可以删除指定位置的元素,当里面是两个参数时,删除的是从第一参数开始,第二个参数是删除元素个数。
scala> c.remove(1)
res27: Int = 2
scala> c
res28: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 98, 87, 76, 65, 21, 4, 5)
scala> c.remove(0,1)
scala> c
res30: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 98, 87, 76, 65, 21, 4, 5)
scala> c.remove(1,3)
scala> c
res32: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 65, 21, 4, 5)
scala> c.remove(2,3)
scala> c
res34: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 65)
Array与ArrayBuffer进行互换
scala> c.toArray
res35: Array[Int] = Array(3, 65)
scala> b.toBuffer
res36: scala.collection.mutable.Buffer[Any] = ArrayBuffer(as, 10)
遍历Array和ArrayBuffer
使用for循环和until遍历Array / ArrayBuffer,until是RichInt提供的函数(也可使用 to 遍历)
scala> for(i<- 0 until b.length) println(b(i))
as
10
scala> for(i<- 0 to b.length-1) println(b(i))
as
10
跳跃遍历Array / ArrayBuffer
首先添加一些元素在遍历
scala> c += (1,2,3,56,8,0,87,5,4,35,67,87,4)
res40: c.type = ArrayBuffer(3, 65, 1, 2, 3, 56, 8, 0, 87, 5, 4, 35, 67, 87, 4)
scala> for(i<- 0 until( c.length,2)) println(c(i))
3
1
3
8
87
4
67
4
从尾部遍历Array / ArrayBuffer
scala> for(i <- (0 until c.length).reverse) println(c(i))
4
87
67
35
4
5
87
0
8
56
3
2
1
65
3
使用“增强for循环”遍历Array / ArrayBuffer
scala> for(e <- c) println(e)
3
65
1
2
3
56
8
0
87
5
4
35
67
87
4
数组常见操作
数组元素求和
scala> c
res45: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 65, 1, 2, 3, 56, 8, 0, 87, 5, 4, 35, 67, 87, 4)
scala> val sum = c.sum
sum: Int = 427
获取最大值
scala> val max = c.max
max: Int = 87
对数组进行排序
获取数组中所有的元素
scala> val a = Array(1,3,2,6,5)
a: Array[Int] = Array(1, 3, 2, 6, 5)
scala> scala.util.Sorting.quickSort(a)
scala> a
res57: Array[Int] = Array(1, 2, 3, 5, 6)
scala> c.mkString
res49: String = 365123568087543567874
scala> c.mkString(",")
res50: String = 3,65,1,2,3,56,8,0,87,5,4,35,67,87,4
scala> c.mkString("<",",",">")
res51: String = <3,65,1,2,3,56,8,0,87,5,4,35,67,87,4>
toString函数
scala> c
res45: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 65, 1, 2, 3, 56, 8, 0, 87, 5, 4, 35, 67, 87, 4)
scala> c.toString
res52: String = ArrayBuffer(3, 65, 1, 2, 3, 56, 8, 0, 87, 5, 4, 35, 67, 87, 4)
scala> b
res54: Array[Any] = Array(as, 10)
scala> b.toString
res53: String = [Ljava.lang.Object;@3f0cad
使用yield和函数式编程转换数组
对Array进行转换,获取的还是Array
scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val a2 = for (ele <- a) yield ele * ele
a2: Array[Int] = Array(1, 4, 9, 16, 25)
对ArrayBuffer进行转换,获取的还是ArrayBuffer
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val b = ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> b +=(1,2,3,4,5)
res1: b.type = ArrayBuffer(1, 2, 3, 4, 5)
scala> val b2 = for(ele <- b) yield ele*2
b2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 4, 6, 8, 10)
结合if守卫,仅转换需要的元素
scala> val a3 = for(ele <- a if ele % 2 == 0 ) yield ele * ele
a3: Array[Int] = Array(4, 16)
使用函数式编程转换数组(通常使用第一种方式)
scala> a.filter(_ % 2 == 0).map(2*_)
res2: Array[Int] = Array(4, 8)
scala> a.filter{_ % 2 == 0}.map{2*_}
res3: Array[Int] = Array(4, 8)
算法案例:移除第一个负数之后的所有负数
// 构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)
// 只要第一个负数,后边的不要了,结果:1, 2, 3, 4, 5, -1
var foundFirstNegative = false
var arrayLength = a.length
var index = 0
while (index < arrayLength) {
if (a(index) >= 0) {
index += 1
} else {
if (!foundFirstNegative) { foundFirstNegative = true; index += 1 }
else { a.remove(index); arrayLength -= 1 }
}
}
算法案例:移除第一个负数之后的所有负数(改良版)
// 重新构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)
keepIndexes (0,1,2,3,4,5)
a(keepIndexes(i))=Array(1,2,3,4,5,-1)
// 每记录所有不需要移除的元素的索引,稍后一次性移除所有需要移除的元素
// 性能较高,数组内的元素迁移只要执行一次即可
var foundFirstNegative = false
val keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield {
if (a(i) < 0) foundFirstNegative = true
i
}
//for (i <- 0 until keepIndexes.length) { a(i) = a(keepIndexes(i)) }
a.trimEnd(a.length - keepIndexes.length)
算法案例:移除第一个负数之后的所有负数(数据很多)
/ 重新构建数组
val a = ArrayBuffer[Int]()
a += (1, 2, 3, 4, 5, -1, -3, -5, -9,6,7,-7,-3,10)
结果:Array(1,2,3,4,5,-1,6,7,10)
val b = ArrayBuffer[Int]()
// 每记录所有不需要移除的元素的索引,稍后一次性移除所有需要移除的元素
// 性能较高,数组内的元素迁移只要执行一次即可
var foundFirstNegative = false
val keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield {
if (a(i) < 0) foundFirstNegative = true
i
}
for (i <- keepIndexes) { b+=a(i) }
Map
创建不可变的Map
scala> val ages = Map("leo"-> 20,"jen"-> 38,"jack"->12)
ages: scala.collection.immutable.Map[String,Int] = Map(leo -> 20, jen -> 38, jack -> 12)
scala> ages("leo")=90
<console>:14: error: value update is not a member of scala.collection.immutable.Map[String,Int]
ages("leo")=90
^
创建可变的Map
scala> val ages = scala.collection.mutable.Map("joker" -> 23,"tyler"-> 21,"lem" -> 45)
ages: scala.collection.mutable.Map[String,Int] = Map(joker -> 23, tyler -> 21, lem -> 45)
scala> ages("tyler")=18
scala> ages
res7: scala.collection.mutable.Map[String,Int] = Map(joker -> 23, tyler -> 18, lem -> 45)
另外一种创建Map(不可修改)
scala> val ages = Map(("leo",23),("jen",34),("joly",11))
ages: scala.collection.immutable.Map[String,Int] = Map(leo -> 23, jen -> 34, joly -> 11)
scala> ages("jen")=57
<console>:14: error: value update is not a member of scala.collection.immutable.Map[String,Int]
ages("jen")=57
^
创建空HashMap
scala> val ages = new scala.collection.mutable.HashMap[String,Int]
ages: scala.collection.mutable.HashMap[String,Int] = Map()
访问Map元素
获取指定key对应的value,如果key不存在,会报错
scala> ages
res9: scala.collection.mutable.HashMap[String,Int] = Map()
scala> ages += ("leo"-> 20,"jen"-> 38,"jack"->12)
res10: ages.type = Map(jack -> 12, jen -> 38, leo -> 20)
scala> val leoage = ages("leo")
leoage: Int = 20
scala> val leoage = ages("Leo")
java.util.NoSuchElementException: key not found: Leo
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.mutable.HashMap.apply(HashMap.scala:65)
... 32 elided
使用contains函数检查key是否存在
scala> val ageleo = if(ages.contains("leo")) ages("leo") else 0
ageleo: Int = 20
getOrElse函数
scala> val leoage = ages.getOrElse("leo",0)
leoage: Int = 20
修改Map元素
增加,删除
scala> ages
res11: scala.collection.mutable.HashMap[String,Int] = Map(jack -> 12, jen -> 38, leo -> 20)
scala> ages += (("mike",34),"tom" -> 40)
res12: ages.type = Map(mike -> 34, jack -> 12, jen -> 38, leo -> 20, tom -> 40)
scala> ages -= "tom"
res13: ages.type = Map(mike -> 34, jack -> 12, jen -> 38, leo -> 20)
更新不可变的Map(不可修改,添加需注意)
scala> val ages = Map("leo"-> 20,"jen"-> 38,"jack"->12)
ages: scala.collection.immutable.Map[String,Int] = Map(leo -> 20, jen -> 38, jack -> 12)
scala> ages("jen") = 12
<console>:14: error: value update is not a member of scala.collection.immutable.Map[String,Int]
ages("jen") = 12
^
scala> val ages2 = ages + ("Mike" -> 36, "Tom" -> 40)
ages2: scala.collection.immutable.Map[String,Int] = Map(jack -> 12, Mike -> 36, Tom -> 40, jen -> 38, leo -> 20)
scala> ages += ("aaa",12)
<console>:14: error: value += is not a member of scala.collection.immutable.Map[String,Int]
ages += ("aaa",12)
^
删除不可变Map的元素
scala> val ages3 = ages - "Tom"
ages3: scala.collection.immutable.Map[String,Int] = Map(leo -> 20, jen -> 38, jack -> 12)
遍历Map
scala> for((key,value) <- ages)println(key + " " + value )
leo 20
jen 38
jack 12
scala> for(key <- ages.keySet)println(key)
leo
jen
jack
scala> for(value <- ages.values) println(value)
20
38
12
//生成新Map,翻转键和值
scala> for((key,value) <- ages) yield (value,key)
res19: scala.collection.immutable.Map[Int,String] = Map(20 -> leo, 38 -> jen, 12 -> jack)
SortedMap和LinkedHashMap
SortedMap可以自动对Map的key的排序,LinkedHashMap可以记住插入entry的顺序
scala> val ages = scala.collection.immutable.SortedMap("leo" -> 30, "alice" -> 15, "jen" -> 25)
ages: scala.collection.immutable.SortedMap[String,Int] = Map(alice -> 15, jen -> 25, leo -> 30)
scala> val ages = new scala.collection.mutable.LinkedHashMap[String,Int]
ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map()
scala> ages("leo")= 33
scala> ages("aaa")= 23
scala> ages("jen")= 34
scala> ages
res23: scala.collection.mutable.LinkedHashMap[String,Int] = Map(leo -> 33, aaa -> 23, jen -> 34)
Map的元素类型------Tuple
简单Tuple
//定义
scala> val t = ("uzi",23,"as")
t: (String, Int, String) = (uzi,23,as)
//访问
scala> t._1
res28: String = uzi
scala> t._3
res29: String = as
zip操作(拉链操作)
scala> val names = Array("leo","joker","tom")
names: Array[String] = Array(leo, joker, tom)
scala> val ages = Array(12,34,32)
ages: Array[Int] = Array(12, 34, 32)
scala> val nameAges = names.zip(ages)
nameAges: Array[(String, Int)] = Array((leo,12), (joker,34), (tom,32))
scala> for((name,age) <- nameAges)println(name + " " + age)
leo 12
joker 34
tom 32