1、迭代器
通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历。
object IteratorDemo {
def main(args: Array[String]): Unit = {
val iterator = List(1, 2, 3, 4, 5).iterator // 得到迭代器
/*
这里我们看看iterator 的继承关系
def iterator: Iterator[A] = new AbstractIterator[A] {
var these = self
def hasNext: Boolean = !these.isEmpty
def next(): A =
if (hasNext) {
val result = these.head; these = these.tail; result
} else Iterator.empty.next()
*/
println("--------遍历方式1 while -----------------")
while (iterator.hasNext) {
println(iterator.next())
}
println("--------遍历方式2 for -----------------")
for(enum <- iterator) {
println(enum) //
}
}
}
小结:
- iterator 的构建实际是 AbstractIterator 的一个匿名子类,该子类提供了
/*
def iterator: Iterator[A] = new AbstractIterator[A] {
var these = self
def hasNext: Boolean = !these.isEmpty
def next(): A =
*/- 该AbstractIterator 子类提供了 hasNext next 等方法
因此,我们可以使用 while的方式,使用hasNext next 方法变量
2、流 Stream
stream是一个集合。这个集合,可以用于存放无穷多个元素,但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循lazy规则(即:要使用结果才进行计算的) 。
object StreamDemo {
def main(args: Array[String]): Unit = {
//创建Stream
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1)
val stream1 = numsForm(1)
println(stream1) // Stream(1,?)
//取出第一个元素
println("head=" + stream1.head) // head=1
println(stream1.tail) // Stream(2, ?)
println(stream1) // Stream(1, 2, ?)
//看一个应用案例
def multi(x:BigInt) : BigInt = {
x * x
}
println(numsForm(5).map(multi)) // Stream(25, ?)
}
}
说明:
- Stream 集合存放的数据类型是BigInt
- numsForm 是自定义的一个函数,函数名是程序员指定的
- 创建的集合的第一个元素是 n , 后续元素生成的规则是 n + 1
- 后续元素生成的规则是可以程序员指定的 ,比如 numsForm( n * 4)…
注意:如果使用流集合,就不能使用last属性,如果使用last集合就会进行无限循环
3、视图 View
Stream的懒加载特性,也可以对其他集合应用view方法来得到类似的效果
特点:
view方法产出一个总是被懒执行的集合
view不会缓存数据,每次都要重新计算,比如遍历View时
请找到1-100 中,数字倒序排列 和它本身相同的所有数。(1 2, 11, 22, 33 …)
object ViewDemo01 {
def main(args: Array[String]): Unit = {
//如果这个数,逆序后和原来数相等,就返回true,否则返回false
def eq(i: Int): Boolean = {
i.toString.equals(i.toString.reverse)
}
//说明: 没有使用view,常规方式
val viewSquares1 = (1 to 100).filter(eq)
println(viewSquares1)
//使用view,来完成这个问题,程序中,对集合进行map,filter,reduce,fold...
//你并不希望立即执行,而是在使用到结果才执行,则可以使用view来进行优化.
val viewSquares2 = (1 to 100).view.filter(eq)
println(viewSquares2)
//遍历
for (item <- viewSquares2) {
println("item=" + item)
}
}
}
Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99)
SeqViewF(...)
item=1
item=2
item=3
item=4
item=5
item=6
item=7
item=8
item=9
item=11
item=22
。。。。
item=99
4、线程安全的集合
所有线程安全的集合都是以Synchronized开头的集合
SynchronizedBuffer
SynchronizedMap
SynchronizedPriorityQueue
SynchronizedQueue
SynchronizedSet
SynchronizedStack
5、并行集合
Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
主要用到的算法有:
-
Divide and conquer : 分治算法,Scala通过splitters(分解器),combiners(组合器)等抽象层来实现,主要原理是将计算工作分解很多任务,分发给一些处理器去完成,并将它们处理结果合并返回
-
Work stealin算法,主要用于任务调度负载均衡(load-balancing),通俗点完成自己的所有任务之后,发现其他人还有活没干完,主动(或被安排)帮他人一起干,这样达到尽早干完的目的
object ParDemo {
def main(args: Array[String]): Unit = {
(1 to 5).foreach(println(_))
println()
//这里输出的结果是无序的,说明是将println任务分配给不同cpu
(1 to 5).par.foreach(println(_))
}
}
object ParDemo {
def main(args: Array[String]): Unit = {
val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}.distinct
val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}.distinct
println(result1) //非并行
println("--------------------------------------------")
println(result2) //并行
}
}
Vector(main)
--------------------------------------------
ParVector(ForkJoinPool-1-worker-5, ForkJoinPool-1-worker-7, ForkJoinPool-1-worker-1, ForkJoinPool-1-worker-3)
6、操作符
- 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号反引号
valval
= 42 - 中置操作符:A 操作符 B 等同于 A.操作符(B)
- 后置操作符:A操作符 等同于 A.操作符,如果操作符定义的时候不带()则调用时不能加括号
- 前置操作符,+、-、!、~等操作符A等同于A.unary_操作符
- 赋值操作符,A 操作符= B 等同于 A = A 操作符 B ,比如 A += B 等价 A = A + B
object OperatorDemo {
def main(args: Array[String]): Unit = {
val n1 = 1
val n2 = 2
val r1 = n1 + n2 // 3
val r2 = n1.+(n2) // 3 看Int的源码即可说明
println(r1)
println(r2)
val monster = new Monster
monster + 10
monster.+(10)
println("monster.money=" + monster.money) // 20
println(monster++)
println(monster.++)
println("monster.money=" + monster.money) // 22
!monster
println("monster.money=" + monster.money) // -22
}
}
class Monster {
var money: Int = 0
//对操作符进行重载 (中置操作符)
def +(n:Int): Unit = {
this.money += n
}
//对操作符进行重载(后置操作符)
def ++(): Unit = {
this.money += 1
}
//对操作符进行重载(前置操作符,一元运算符)
def unary_!(): Unit = {
this.money = -this.money
}
}
3
3
monster.money=20
()
()
monster.money=22
monster.money=-22
7、综合练习
练习1:
val sentence = “AAAAAAAAAABBBBBBBBCCCCCDDDDDDD”
将sentence 中各个字符,通过foldLeft存放到 一个ArrayBuffer中
object Exercise {
def main(args: Array[String]): Unit = {
val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
val arrayBuffer = new ArrayBuffer[Char]()
sentence.foldLeft(arrayBuffer)(putArray)
println("arrayBuffer=" + arrayBuffer)
}
def putArray(arr:ArrayBuffer[Char],c:Char): ArrayBuffer[Char] = {
//将c 放入到arr 中
arr.append(c)
arr
}
}
arrayBuffer=ArrayBuffer(A, A, A, A, A, A, A, A, A, A, B, B, B, B, B, B, B, B, C, C, C, C, C, D, D, D, D, D, D, D)
练习2:
val sentence = “AAAAAAAAAABBBBBBBBCCCCCDDDDDDD”
使用映射集合,统计一句话中,各个字母出现的次数
Java:
String sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD";
Map<Character, Integer> charCountMap =
new HashMap<Character, Integer>();
char[] cs = sentence.toCharArray();
for ( char c : cs ) {
if ( charCountMap.containsKey(c) ) {
Integer count = charCountMap.get(c);
charCountMap.put(c, count + 1);
} else {
charCountMap.put(c, 1);}}
System.out.println(charCountMap);
Scala:
object Exercise {
def main(args: Array[String]): Unit = {
val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
val map2 = sentence.foldLeft(Map[Char,Int]())(charCount)
println("map2=" + map2)
//使用可变的map,效率更高.
//1. 先创建一个可变map,作为左折叠的第一个参数
val map3 = mutable.Map[Char,Int]()
sentence.foldLeft(map3)(charCount2)
println("map3=" + map3)
}
//使用不可变map实现
def charCount(map:Map[Char,Int],char:Char): Map[Char,Int] = {
map + (char -> (map.getOrElse(char,0) + 1) )
}
//使用可变map实现
def charCount2(map:mutable.Map[Char,Int], char:Char): mutable.Map[Char,Int] = {
map += (char -> (map.getOrElse(char,0) + 1) )
}
}
map2=Map(A -> 10, B -> 8, C -> 5, D -> 7)
map3=Map(D -> 7, A -> 10, C -> 5, B -> 8)
练习3:
val lines = List(“fjw bbb hello world”, “fjw bbb aaa aaa aaa ccc ddd uuu”)
使用映射集合,list中,各个单词出现的次数,并按出现次数排序
object WorldCount {
def main(args: Array[String]): Unit = {
val lines = List("fjw bbb hello world", "fjw bbb aaa aaa aaa ccc ddd uuu")
val res1 = lines.flatMap(_.split(" "))
println("res1=" + res1)
// res1.map 说明
//1. 使用map,返回对偶元组 形式为
//List((hello,1), (tom,1), (hello,1), (jerry,1), (hello,1), (jerry,1), (hello,1), (kitty,1))
val res2 = res1.map((_, 1))
println("res2=" + res2)
// res2.groupBy(_._1)
//1. 分组的根据是以元素来分组
//2. _._1 中的第一个 _ 表示取出的各个对偶元组比如 (hello,1)
//3. _._1 中的_1, 表示对偶元组的第一个元素,比如 hello
//4. 因此 _._1 表示我们分组的标准是按照对偶元组的第一个元素进行分组
//5. 返回的形式为 Map(tom -> List((tom,1)), kitty -> List((kitty,1)), jerry -> List((jerry,1), (jerry,1)), hello -> List((hello,1), (hello,1), (hello,1), (hello,1)))
val res3 = res2.groupBy(_._1)
println("res3=" + res3)
// x=>(x._1, x._2.size) 传入一个匿名函数,完成统计
//1.x 表示传入的Map中的各个元素,比如 jerry -> List((jerry,1), (jerry,1))
//2.x._1 表示 jerry
//3.x._2.size,表示对 List((jerry,1), (jerry,1))求size,是多少就是多少
//4.结果是 res4=Map(han -> 2, atguigu -> 2, hello -> 1)
//5.到此结果就出来了,但是没有排序
val res4 = res3.map(x=>(x._1, x._2.size))
println("res4=" + res4 )
// res4.toList.sortBy(_._2)
//1. toList先将map转成 list,为了下一步排序
//5. sortBy就是排序,以对偶元组的第二个值排序,就是大小排序
val res5 = res4.toList.sortBy(_._2)
println("res5=" + res5)
//如果希望从大到小排序,执行reverse即可
val res6 = res5.reverse
println("res6=" + res6)
}
}
res1=List(fjw, bbb, hello, world, fjw, bbb, aaa, aaa, aaa, ccc, ddd, uuu)
res2=List((fjw,1), (bbb,1), (hello,1), (world,1), (fjw,1), (bbb,1), (aaa,1), (aaa,1), (aaa,1), (ccc,1), (ddd,1), (uuu,1))
res3=Map(world -> List((world,1)), ddd -> List((ddd,1)), ccc -> List((ccc,1)), uuu -> List((uuu,1)), bbb -> List((bbb,1), (bbb,1)), hello -> List((hello,1)), aaa -> List((aaa,1), (aaa,1), (aaa,1)), fjw -> List((fjw,1), (fjw,1)))
res4=Map(world -> 1, ddd -> 1, ccc -> 1, uuu -> 1, bbb -> 2, hello -> 1, aaa -> 3, fjw -> 2)
res5=List((world,1), (ddd,1), (ccc,1), (uuu,1), (hello,1), (bbb,2), (fjw,2), (aaa,3))
res6=List((aaa,3), (fjw,2), (bbb,2), (hello,1), (uuu,1), (ccc,1), (ddd,1), (world,1))