初识 array,list,set,map,元组 等
//定长数组
val arr1 = new Array[Int](10)
//变长数组
val arr2 = new ArrayBuffer[Int]()
//定长数组与变长数组的转换
arr1.toBuffer
arr2.toArray
//元组进行循环遍历的方法:
val tuple1 = (1, 2, 3, "heiheihei")
//方式1:
for (elem <- tuple1.productIterator) {
println(elem)
}
//方式2:
tuple1.productIterator.foreach(i => println(i))
tuple1.productIterator.foreach(print(_))
列表:List
// 创建List(只有不可变的:scala.collection.immutable.List, mutable下没有)
val list1 = List(1, 2)
//List元素的追加
//添加到列表的末尾
val list2 = list1 :+ 99
println(list2)
//添加到列表的首位
val list3 = 100 +: list1
println(list3)
//List的创建与追加,使用符号“::”
val list4 = 1 :: 2 :: 3 :: list1
println(list4)
// 从头部开始删除 n 元素
// def drop(n: Int): List[A]
// 等同于 List(1, 2, 3, 4, 5).drop(2)
println(List(1, 2, 3, 4, 5) drop 2)
// List(3, 4, 5)
//partition:按照某种条件对数据进行分类
//def partition(p: A => Boolean): (Repr, Repr)
println(List(1, 2, 3, 4, 5) partition (_ % 2 == 0))
//(List(2, 4),List(1, 3, 5))
//find:查找集合第一个符合条件的元素
//def find(p: A => Boolean): Option[A]
println(List(1, 2, 3, 4, 5) find (_ % 2 == 0)) //Some(2)
println(List(1, 2, 3, 4, 5) find (_ <= 0)) //None
//takeWhile:逐个匹配符合条件的元素 直到不符合条件 之后的元素不在判断
//override def takeWhile(p: A => Boolean): List[A]
println(List(2, 3, 2, 3, 5,1,0) takeWhile (_ < 4))
//List(2, 3, 2, 3)
//dropWhile:着个匹配 去除 符合条件的元素 直到不符合条件 之后的元素不在判断
//override def dropWhile(p: A => Boolean): List[A]
println(List(1, 2, 6, 4, 5) dropWhile (_ < 4))
//List(6, 4, 5)
映射 Map
//1) 构造不可变映射
//默认是 scala.collection.immutable 下的Map
val map1 = Map("Alice" -> 10, "Bob" -> 20, "Kotlin" -> 30)
//2) 构造可变映射
val map2 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 20, "Kotlin" -> 30)
//3) 构造映射的第二种方式:对偶元组
val map4 = Map(("Alice", 10), ("Bob", 20), ("Kotlin", 30))
//4) 取值,两种方式
val value1 = map1("Alice")//建议使用get方法得到map中的元素
println(value1)
// getOrElse:如果key对应的value没有,则返回默认值
println(map1.getOrElse("Alice",60))
//更新值
map2("Alice") = 99
//或:
map2 += ("Bob" -> 99)
// += 也可以用于添加元素
map2 += ("CCC" -> 30)
// -= 用于删除元素
map2 -= "Alice"
// 删除多个元素
map2 -= ("CCC", "Kotlin")
//添加多个元素,并给一个新的变量
val map5 = map2 + ("AAA" -> 10, "BBB" -> 20)
//6) 遍历
for ((k, v) <- map1) println(k + " is mapped to " + v)
for (v <- map1.keys) println(v)
for (v <- map1.values) println(v)
for(v <- map1) prinln(v)
集 Set 集是不重复元素的结合。
//如果想要按照已排序的顺序来访问集中的元素,可以使用SortedSet(已排序数据集)
//默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,
//需要引用 scala.collection.mutable.Set 包。
//1) Set不可变集合的创建
val set = Set(1, 2, 3, 3)
println(set) // 输出为 Set(1, 2, 3)
//2) Set可变集合的创建
import scala.collection.mutable.Set
val mutableSet = Set(1, 2, 3)
//3) 可变集合的元素添加
mutableSet.add(4)
mutableSet += 4
// 注意该方法返回一个新的Set集合,而非在原有的基础上进行添加
mutableSet.+(5) //或表达成:mutableSet + 5
//4) 可变集合的元素删除
mutableSet -= 1
mutableSet.remove(2)
println(mutableSet)
//5) 遍历
for(x <- mutableSet) {
println(x)
}
List、Array、Set、元组 区别
-
List列表:不可变
LIst支持在头部快速添加和移除条目,但是不提供快速按下标访问的功能,这个功能需要线性遍历列。List列表跟数组非常像,同一个列表的所有元素必须是相同类型。
但是有2个重要区别:
1、List是不可变的,元素不能通过赋值改变。
2、列表的结构本质是链表(即linkedList) -
Array数组
提供下标高效访问(获取或更新)指定位置的元素 -
数组缓冲ArrayBuffer:可变
跟Array很像,除了可以额外地从序列头部或尾部添加或移除元素。
所有的Array操作在ArrayBuffer都可用。 -
集Set,提供了可变和不可变
每个元素对象最多出现一次 -
元组,可以存放不同类型的数据
集合元素与函数的映射
//***1) map:将集合中的每一个元素映射到某一个函数***
val names = List("Alice", "Bob", "Nick")
//转成大写
println(names.map(_.toUpperCase))
val age = List(20, 22, 23)
//每个元素 + 2
println(age.map(_ + 2))
//2) flatmap:flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合
val names = List("Alice", "Bob", "Nick")
println(names.flatMap(_.toUpperCase()))
//结果为: List(A, L, I, C, E, B, O, B, N, I, C, K)
val sort = List(List(1, 2, 3), List(4, 5, 6))
println(sort.flatMap(i => {
i.map(_ * 2)
}))
//结果为:List(2, 4, 6, 8, 10, 12)
reduce、fold、scan
//1) reduce:将二元函数应用于集合中的函数
//先取出前两个元素,执行运算,得到的结果再和后面的元素 继续执行运算
val list = List(1, 2, 3, 4, 5)
// 对集合中的每一个元素执行 相加 操作
// 1 + 2 + 3 + 4 + 5 = 15
val i4 = list.reduce(_ + _)
// 相当于 list.reduce((x, y) => x + y)
println(i4)
// 对集合中的每一个元素执行 相减 操作
// 1 - 2 - 3 - 4 - 5 = -13
val i3 = list.reduce(_ - _)
println(i3)
// reduce 相当于 reduceLeft
val i1 = list.reduceLeft(_ - _)
println(i1)
// 对集合中的每一个元素 从右往左 执行 相减 操作
// 1 - (2 - (3 - (4 - 5))),结果为 3
val i2 = list.reduceRight(_ - _)
println(i2)
- fold
foldLeft,从左往右遍历元素
val list2 = List(1, 2, 3, 4)
val i4 = list2.foldLeft(1)(_ + _)
println(i4)
执行过程为:1 + 1 + 2 + 3 + 4 = 11
也就是说,foldLeft和reduceLeft的区别就是,指定了一个初始值,在进行运算的时候,先让这个初始值和集合中的第一个元素进行运算。
list2.foldLeft(0)(_ + ) 相当于 list2.reduceLeft( + _)
通过下面的代码来看一下 执行过程:
val list2 = List(1, 2, 3, 4, 5)
val i4 = list2.foldLeft(-2) {
(x, y) => {
println("x: " + x + ", y: " + y)
x + y
}
}
println(i4)
结果为:
x: -2, y: 1
x: -1, y: 2
x: 1, y: 3
x: 4, y: 4
x: 8, y: 5
13
foldRight
从右往左执行
val i5 = list2.foldRight(-2)(_ - _)
println(i5)
看下执行过程:
val i5 = list2.foldRight(-2) {
(x, y) => {
println("x: " + x + ", y: " + y)
x + y
}
}
println(i5)
x: 5, y: -2
x: 4, y: 3
x: 3, y: 7
x: 2, y: 10
x: 1, y: 12
fold、foldLeft、foldRight的区别:fold的初始值的类型必须是集合中元素类型的超类
下面的例子会报错,因为初始值MapChar, Int 的类型Map不是 集合元素类型:Char 的父类。
val str = "aaadfasfwef"
val i5 = str.fold(Map[Char, Int]()) {
(map, word) => {
map + (word -> (map.getOrElse(word, 0) + 1))
}
}
println(i5)
尖叫提示:foldLeft和foldRight有一种缩写方法对应分别是:/:和:
例如:
foldLeft
// 相当于 list2.fold(1)(_ + _)
val i6 = (2 /: list2)(_ - _)
println(i6)
// 相当于 list2.foldRight(2)(_ + _)
val i7 = (list2 :\ 2)(_ - _)
println(i7)
- 统计一句话中,各个文字出现的次数
val sentence = "哈哈嘿嘿哈哈呵呵哈吼吼哈嘻嘻"
val i8 = (Map[Char, Int]() /: sentence)((m, c) => m + (c -> (m.getOrElse(c, 0) + 1)))
println(i8)
分析:
Map[Char, Int]
相当于:val map = MapChar, Int
(m, c) => m + (c -> (m.getOrElse(c, 0) + 1))
相当于 map + (‘哈’ -> (map.getOrElse(‘哈’, 0) + 1)),
先取第一个 ‘哈’,刚开始 map中没值,map.getOrElse(‘哈’, 0) 返回0,
则上面的式子相当于:map + (‘哈’ -> 1),
会产生一个新的map,元素为:‘哈’ -> 1;
然后取第二个 ‘哈’,map + (‘哈’ -> (map.getOrElse(‘哈’, 0) + 1))
这时map.getOrElse(‘哈’, 0)返回1,
则上面的式子相当于:map + (‘哈’ -> 2),
因为map中已存在元素:‘哈’ -> 1,所以会对value进行更新,则map中的元素为:‘哈’ -> 2
- scan
这个理解需要结合上面的知识点,扫描,相当于fold操作,只不过会把产生的所有中间结果放置于一个集合中保存。
// 5 1 2 3 4
val i9 = (1 to 4).scanLeft(5)(_ + _)
println(i9)
结果为:Vector(5, 6, 8, 11, 15)
拉链
zip命令可以将多个值绑定在一起
val name = Array("xiaoming", "xiaoliang", "xiaoli")
val score = Array(85, 80, 30)
name.zip(score)
val result = name.zip(score)
for (i <- result) {
println(i)
}
输出,结果为:
(xiaoming,85)
(xiaoliang,80)
(xiaoli,30)
注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数
迭代器
你可以通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历。
val iterator = List(1, 2, 3, 4, 5).iterator
while (iterator.hasNext) {
println(iterator.next())
}
//或:
for(enum <- iterator) {
println(enum)
}
并行集合
Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
将计算工作分解很多任务,分发给一些处理器去完成,并将它们处理结果合并返回
(1 to 5).foreach(println(_))
println()
(1 to 5).par.foreach(println(_))
// 查看运行在哪些线程,Fork/Join框架是一个用于并行执行任务的框架
(1 to 20).par.foreach(i => {
println(i + "," + Thread.currentThread().getName)
})