数组定义

数组几乎是所有语言中最基础的数据结构。数组可索引、类型一致、长度不变。

在Scala中,数组分为定长数组和变长数组。

  • 定长数组,Array,长度是不变的

  • 变长数组,ArrayBuffer,长度是可变的,它等效于Java中的ArrayList

    变的数组类型,使用可变数组类型时需要显示声明;

    使用ArrayBuffer时,需要导包 import scala.collection.mutable.ArrayBuffer;

Scala 中很多数组类型都有可变、不可变两个版本,推荐使用不可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package lagou.cn.part03

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

/**
* 使用变长数组之前需要导入包scala.collection.mutable.ArrayBuffer
*/
object ArrayDemo {
def main(args: Array[String]): Unit = {
println("===========定长数组================")
//定义长度为10的整型数组,初始值为0
val nums = new Array[Int](10)
//定义长度为10的字符串数组,初始值为null
val strs = new Array[String](10)
//访问数组元素,索引从0开始,使用()而不是[]来访问元素
println(strs(0))

//省略了关键字new,那么Scala会进行自动类型推断
val arrays: Array[Int] = Array(1, 2, 3, 4)
val arrays2: Array[Nothing] = Array()
println(arrays.length)

//通过toArray快速定义数组,用于测试
val numsList: Array[Int] = (1 to 10).toArray

println("===========变长数组================")
//定义一个空的Int的变长数组
//注意:后面要有小括号
val numsBuffer = ArrayBuffer[Int]()

//通过+=在尾端添加一个或多个元素
numsBuffer += 1
numsBuffer += (2, 3, 4, 5)
//通过++=在尾端添加集合
numsBuffer ++= Array(6, 7, 8)
numsBuffer.foreach(println(_))
//还可通过-= --=对变长数组进行删减
numsBuffer -= 8
numsBuffer --= Array(6, 7)
println("============删减后的变长数组=============")
numsBuffer.foreach(println(_))

//使用append追加一个或多个元素
numsBuffer.append(1)
numsBuffer.append(2, 3, 4)
println("============追加后的变长数组=============")
numsBuffer.foreach(println(_))

//在某索引之前插入元素
numsBuffer.insert(2,10)
numsBuffer.insert(2,20,30)
println("============插入后的变长数组=============")
numsBuffer.foreach(println(_))

//移除元素
//trimEnd移除最后的N个元素
numsBuffer.trimEnd(3)
//trimStart移除去最开始的一个或多个元素
numsBuffer.trimStart(2)
println("============移除后的变长数组=============")
numsBuffer.foreach(println(_))

//通过remove从某索引处移除一个或多个元素
numsBuffer.remove(3)
numsBuffer.remove(2,3)
println("============remove后的变长数组=============")
numsBuffer.foreach(println(_))

}
}

数组操作

  • 数组转换

    上述代码ArrayDemo对象中添加以下:

    1
    2
    3
    4
    //toArray,变长数组转换为定长数组
    val numArray: Array[Int] = numsBuffer.toArray
    //toBuffer,定长数组转换为变长数组
    val arrayBuffer: mutable.Buffer[Int] = arrays.toBuffer
  • 数组遍历

    上述代码ArrayDemo对象中添加以下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    println("==================数组遍历=======================")
    println("===============使用until进行数组遍历==============")
    for(i <- 0 until(arrays.length)){
    println(arrays(i))
    }
    println("===============使用to进行数组遍历==============")
    for (i <- 0 to arrays.length-1){
    println(arrays(i))
    }
    println("===============使用增强for循环的方式进行数组遍历==============")
    for(elem <- arrays) println(elem)
    println("===============使用foreach进行数组遍历==============")
    arrays.foreach(println(_))

常见算法

在Scala中对数组进行转换非常简单方便,这些转换动作不会修改原始数组,而是产生一个全新的数组。

任务:将数组中偶数元素加倍,奇数元素丢弃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package lagou.cn.part03

object OperatorDemo {
def main(args: Array[String]): Unit = {
//将数组中的偶数加倍,奇数丢弃
val nums = (1 to 10).toArray
val result1 = for (elem <- nums if elem % 2 == 0) yield elem * 2
val result2 = for (elem <- nums) yield if (elem % 2 == 0) elem * 2 else 0
result1.foreach(println(_))
println("=============================")
result2.foreach(println(_))

//使用Scala中的高阶函数来实现
nums.filter(_ % 2 == 0).map(_ * 2).foreach(println(_))

println("=============================")
//获取第一个元素
println(nums.head)
//获取最后一个元素
println(nums.last)
//获取除了第一个元素之外的其他元素
println(nums.tail.toBuffer)
//获取除了最后一个元素之外的其他元素
println(nums.init.toBuffer)

//求和
println(nums.sum)
//求最大值
println(nums.max)
//求最小值
println(nums.min)

val nums2 = Array(2, 1, 4, 3)
//数组元素排序,升序
println(nums2.sorted.toBuffer)
//元素相乘
println(nums2.product)

println("====================================")
val nums3 = Array(1, 2, 3, 4, 3, 2, 1)
println(nums3.map(_ * 2).toBuffer)
println(nums3.reduce(_ + _))
//将数组中的数据进行去重
println(nums3.distinct.toBuffer)
println(nums3.length)
println(nums3.size)
//获取数组中每个元素的索引
println(nums3.indices.toBuffer)

//使用mkString进行输出
println(nums3.mkString(" & "))
println(nums3.mkString("<", " & ", ">"))

//count计数,注意:count后面必须有条件
println(nums3.count(_ > 2))
println(nums3.count(_ % 2 == 0))

//filter过滤出符合条件的数据; filterNot过滤出不符合条件的数据
println(nums3.filter(_ > 2).toBuffer)
println(nums3.filterNot(_ % 2 == 0).toBuffer)

println("========================================")
//take提取前N个元素
println(nums3.take(3).toBuffer)
//takeRight提取后N个元素
println(nums3.takeRight(4).toBuffer)
//takeWhile从左向右进行提取,提取出符合条件的元素,如果条件不成立就终止提取
println(nums3.takeWhile(_ < 4).toBuffer)

println("========================================")
//删除前N个元素
println(nums3.drop(3).toBuffer)
//删除后N个元素
println(nums3.dropRight(3).toBuffer)
//从左向右删除符合条件的元素,如果条件不成立,就终止删除操作
println(nums3.dropWhile(_ < 4).toBuffer)

println("========================================")
//将数组分为两部分,前N个为一部分,剩下的为另一部分
val tuple: (Array[Int], Array[Int]) = nums3.splitAt(3)
println(tuple._1.toBuffer + " " + tuple._2.toBuffer)
//对数组进行切片操作,取出从索引2到索引4的元素,不包括索引为5的元素
println(nums3.slice(2, 5).toBuffer)

println("========================================")
val array1 = Array("A", "B", "C")
val array2 = Array(1, 2, 3, 4)
//拉链操作,当两个数组的长度不一样时,截取相同的长度
val z1: Array[(String, Int)] = array1.zip(array2)
println(z1.toBuffer)

//拉链操作,当两个数组长度不一样时,array1用*填充,array2用-1填充
val z2 = array1.zipAll(array2, "*", -1)
//拉链操作,当两个数组长度不一样时,array2用*填充,array1用-1填充
val z3 = array2.zipAll(array1, "*", -1)
//用数组索引进行填充
val z4 = array1.zipWithIndex
println(z2.toBuffer)
println(z3.toBuffer)
println(z4.toBuffer)

println("========================================")
//通过unzip进行拆分数组的操作
// 通过unzip把z4拆分成两个数组
val (l1, l2) = z4.unzip
println(l1.toBuffer)
println(l2.toBuffer)

val (l3, l4, l5) = Array((1, "one", '1'), (2, "two", '2'), (3, "three", '3')).unzip3
println(l3.toBuffer)
println(l4.toBuffer)
println(l5.toBuffer)

//数组的操作符::+ +: ++
// :+用于在数组的尾部追加元素; +:用于在数组的头部追加元素
// ++用于连接两个集合(比如:数组、列表等)
val num1 = (1 to 4).toArray
val num2 = (5 to 8).toArray

val num3 = 10 +: num1
val num4 = num2 :+ 9
val num5 = num1 ++ num2
println("========================================")
println(num3.toBuffer)
println(num4.toBuffer)
println(num5.toBuffer)

println("===========数组排序==============")
val sortNums=Array(1,3,5,2,7,8,6,9)
//升序
println(sortNums.sorted.toBuffer)
//降序
println(sortNums.sorted.reverse.toBuffer)
//降序
println(sortNums.sortWith(_>_).toBuffer)
//升序
println(sortNums.sortWith(_<_).toBuffer)

}
}

多维数组

通过Array的ofDim方法来定义一个多维的数组,多少行,多少列,都是自己说了算。

1
2
3
4
5
6
7
8
9
10
11
object MultipleArrayDemo {
def main(args: Array[String]): Unit = {
//定义一个3行4列的二维数组
val dim = Array.ofDim[Double](3, 4)
dim(1)(1) = 12.5
for (i <- 0 to 2; j <- 0 to 3){
print(dim(i)(j)+" ")
if(j==3) println()
}
}
}

元组及操作

Tuple,元组。Map是键值对的集合。对偶是元组的最简单形态;

元组是不同类型的值的集合,元组中的元素可以是不同的数据类型,元组在Scala中的应用非常广泛。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package lagou.cn.part03

/**
* Tuple元组,可以存放不同数据类型的元素
* 元组的索引从1开始,不是从0开始
* 元组在Scala中应用非常广泛,在Spark的源码中会见到很多元组。
* 在Scala中,已经事先定义好了22个Tuple,从Tuple1~~Tuple22
* 在Tuple22中,最多只能有22个元素
*/
object TupleDemo {
def main(args: Array[String]): Unit = {
//定义一个元组
val tuple = (1, 2.5, "spark", 'a', true)
val tuple2 = (1, 1.2, "scala", 'b')
println(tuple == tuple2)

println(tuple._3)

//从元组中接收数据
val (t1, t2, t3, t4), t5 = tuple2
println(s"$t1 $t2 $t3 $t4")

val (b1,_,b2,_),b5=tuple2
println(s"$b1 $b2")

//遍历元组
for (t <- tuple.productIterator){
println(t)
}
println("===========================")
tuple.productIterator.foreach(println(_))

}
}