Scala——集合

7 集合

7.1 集合简介

集合简介:

(1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable特质。

(2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable

(3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象

(4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于 java 中 StringBuilder 对象

建议:在操作集合的时候,不可变用符号,可变用方法

7.2 数组

  1. 不可变数组
    定义:val arr1 = new Array[Int](10)

(1)new 是关键字
(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any
(3)(10),表示数组的大小,确定后就不可以变化

package com.yu.chapter07

object test_ImmutableArray {
  def main(args: Array[String]): Unit = {
    //1. 创建数组
    val arr = new Array[Int](5)
    //另一种调用方式 内部调用了apply方法
    val arr1 = Array(12, 12, 13, 14, 15)

    //2. 访问元素
    println(arr(0))   //0  默认为0
    println(arr1(4))  //15

    //3. 数组赋值
    arr(0) = 2
    arr(1) = 8
    arr(2) = 9
    println(arr(1)) //8

    //4. 数组遍历
    //(1) for循环
    for (i <- 0 until arr.length){
      println(arr(i))
    }
    for (i <- arr.indices) println(arr(i))

    //(2) 增强for循环 直接遍历所有元素
    for (elem <- arr1) println(elem)

    //(3) 迭代器
    val iter = arr1.iterator
    while (iter.hasNext)
      println(iter.next())

    //(4)foreach 方法
    arr1.foreach((elem: Int) => println(elem))
    arr.foreach(println)
    println(arr.mkString("--"))
    //2--8--9--0--0

    //5. 添加元素
    val arr2 = arr1.:+(22)  //尾部添加,原数组是不可变的,只能赋值给新的数组
    println(arr2.mkString("--"))
    //12--12--13--14--15--22

    val arr3 = arr1.+:(33)  //在前面添加
    println(arr3.mkString("--"))
    //33--12--12--13--14--15

    val arr4 = arr1 :+ 19  //省略点号的操作, :+ 左右各一个空格
    val arr5 = 29 +: arr4  //冒号指定了方向,从右往左结合,所以应该反过来,把数组放在后面
    val arr6 = 19 +: 29 +: arr4 :+ 33 :+ 3
    println(arr4.mkString("--"))
    println(arr5.mkString("--"))
    println(arr6.mkString("--"))
    //12--12--13--14--15--19
    //29--12--12--13--14--15--19
    //19--29--12--12--13--14--15--19--33--3
  }
}
  1. 可变数组

val arr01 = ArrayBuffer[Any](3, 2, 5)
(1)[Any]存放任意数据类型
(2)(3, 2, 5)初始化好的三个元素
(3)ArrayBuffer 需要引入 scala.collection.mutable.ArrayBuffer

  1. 不可变数组与可变数组的转换

arr1.toBuffer //不可变数组转可变数组
arr2.toArray //可变数组转不可变数组
(1)arr2.toArray 返回结果才是一个不可变数组,arr2 本身没有变化
(2)arr1.toBuffer 返回结果才是一个可变数组,arr1 本身没有变化

package com.yu.chapter07

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

object test_ArrayBuffer {
  def main(args: Array[String]): Unit = {
    //1. 创建可变数组
    val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
    val arr2 = ArrayBuffer(12, 22, 32, 43)
    println(arr1.mkString("--"))
    println(arr2)
    //
    //ArrayBuffer(12, 22, 32, 43)    //第一个输出的是空,里面无值

    //2. 访问元素
    //println(arr1(0))  //会报错,数组越界,arr1是空的
    println(arr2(0))
    //12
    arr2(1) = 32
    println(arr2(1))    //32 数组修改

    //3. 添加元素
    arr1 += 10
    println(arr1)
    //ArrayBuffer(10)

    val arr3 = arr1 += 11
    println(arr3)
    println(arr1)
    println(arr3 == arr1)
    //ArrayBuffer(10, 11)
    //ArrayBuffer(10, 11)
    //true
    //把 arr1 的引用赋给了arr3 arr3发生改变,arr1也会相同的改变 首部添加使用 +=:
    //使用append方法
    arr1.append(33)
    arr1.prepend(22)  //首部添加
    arr1.insert(1, 33)
    println(arr1)
    //ArrayBuffer(22, 33, 10, 11, 33)
    arr1.insertAll(0, arr1)  //添加一个数组
    arr1.prependAll(arr1)    //首部添加一个数组
    println(arr1)
    //ArrayBuffer(22, 33, 10, 11, 33, 22, 33, 10, 11, 33, 22, 33, 10, 11, 33, 22, 33, 10, 11, 33)

    //4. 删除元素
    arr2.remove(2)    //删去索引位置12 的值
    arr2.remove(0, 2)  //连续删除两个数
    println(arr2)
    //ArrayBuffer(43)
    arr1 -= 33    //删去第一个值为33的数
    println(arr1)

    //5. 可变数组转换为不可变数组
    val arr: ArrayBuffer[Int] = ArrayBuffer(23, 34, 45)
    val newArr: Array[Int] = arr.toArray   //转换为Array
    println(newArr.mkString(","))
    println(arr)
    //23,34,45
    //ArrayBuffer(23, 34, 45)

    //6. 不可变数组转换为可变数组
    val buffer: mutable.Buffer[Int] = newArr.toBuffer
    println(buffer)
    println(newArr)
    //ArrayBuffer(23, 34, 45)
    //[I@4c203ea1
  }
}
  1. 多维数组

val arr = Array.ofDim[Double](3,4)
说明:二维数组中有三个一维数组,每个一维数组中有四个元素

package com.yu.chapter07

object test_mulArray {
  def main(args: Array[String]): Unit = {
    //1. 创建二维数组
    val array: Array[Array[Int]] = Array.ofDim[Int](n1 = 2, n2 = 3)
    //2. 访问元素
    array(0)(1) = 19
    array(1)(1) = 3
    println(array(0)(1))
    for (i <- 0 until array.length; j <- 0 until array(i).length){
      println(array(i)(j))
    }
    for (i <- array.indices; j <- array(i).indices){
      print(array(i)(j) + "\t")
      if (j == array(i).length-1) println()
    }
    //0	19	0
    //0	3	0
    array.foreach(line => line.foreach(println))
    array.foreach(_.foreach(println))
  }
}

7.3 列表List

  1. 不可变List

(1)List 默认为不可变集合,数据有顺序,可以重复
(2)空集合Nil
(3)集合间合并:将一个整体拆成一个一个的个体,称为扁平化

  1. 可变ListBuffer
package com.yu.chapter07

import scala.collection.mutable.ListBuffer

object test_ListBuffer {
  def main(args: Array[String]): Unit = {
    //1. 创建可变列表
    val list1: ListBuffer[Int] = new ListBuffer[Int]()
    val list2 = ListBuffer(12, 23, 34)
    println(list1) //ListBuffer()
    println(list2) //ListBuffer(12, 23, 34)

    //2. 添加元素
    list1.append(56)
    list1.prepend(78)
    list1.insert(1, 89)
    println(list1)   //ListBuffer(78, 89, 56)
    34 +=: 45 +=: list1 += 56 += 78  //前面后面各加两个  冒号在末尾,从右到左调用
    println(list1)
    //ListBuffer(34, 45, 78, 89, 56, 56, 78)

    //3. 合并list
    val list3 = list1 ++ list2  //list1 和 list2 不发生改变,返回一个新的list
    println(list3) //ListBuffer(34, 45, 78, 89, 56, 56, 78, 12, 23, 34)

    list1 ++= list2
    println(list1) //ListBuffer(34, 45, 78, 89, 56, 56, 78, 12, 23, 34) list2不变

    list1 ++=: list2 //在list2上追加list1 ,list1不变
    println(list2) //ListBuffer(34, 45, 78, 89, 56, 56, 78, 12, 23, 34, 12, 23, 34)

    //4. 修改元素
    list2(2) = 33  //修改索引位置2的元素为33
    println(list2)
    
    //5. 删除元素
    list1.remove(2)
    list1.remove(2, 3)
    list1 -= 34
    //打印
    list1.foreach(println)
  }
}

7.4 Set集合

默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用scala.collection.mutable.Set 包

  1. 不可变Set

(1)Set 默认是不可变集合,数据无序
(2)数据不可重复
(3)遍历集合

package com.yu.chapter07

object test_ImmutableSet {
  def main(args: Array[String]): Unit = {
    //1. 创建不可变集合
    val set1 = Set(1, 23, 24, 33, 44, 33)
    println(set1)   //自动去除重复数据
    //HashSet(24, 1, 33, 44, 23)

    //2. 添加元素
    val set2 = set1.+(20) //set1不变
    println(set2) //HashSet(24, 20, 1, 33, 44, 23) 无序
    val set3 = set1 + 56
    println(set3) //HashSet(56, 24, 1, 33, 44, 23)

    //3.合并Set
    val set4 = Set(22, 45, 73, 97)
    val set5 = set2 ++ set4
    println(set5) //HashSet(24, 20, 1, 33, 97, 73, 45, 23, 22, 44)

    //4. 删除元素
    val set6 = set2 - 20
    println(set6) //HashSet(24, 1, 33, 44, 23)
  }
}
  1. 可变 mutable.Set
package com.yu.chapter07

import scala.collection.mutable

object test_MutableSet {
  def main(args: Array[String]): Unit = {
    //1. 创建可变集合
    val set1: mutable.Set[Int] = mutable.Set(13, 24, 57, 36)
    println(set1)  //HashSet(24, 57, 36, 13)

    //2. 添加元素
    set1 + 11 //这种方式只会返回一个新的对象,set1本身并没有添加元素
    println(set1)  //HashSet(24, 57, 36, 13)
    set1 += 111
    println(set1)  //HashSet(24, 57, 36, 13, 111)
    set1.add(88)

    //3. 删除元素
    set1 -= 24
    set1.remove(57)
    println(set1) //HashSet(36, 88, 13, 111)

    //4. 合并两个Set
    val set3 = mutable.Set(22, 89, 45, 20)
    val set4 = set1 ++ set3
    println(set4) //HashSet(20, 36, 22, 88, 89, 13, 45, 111)
    set1 ++= set3   //set1元素与set4相同
  }
}

7.5 Map集合

Scala 中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对(key-value)映射。

  1. 不可变Map
package com.yu.chapter07

object test_ImmutableMap {
  def main(args: Array[String]): Unit = {
    //1. 创建map
    val map1: Map[String, Int] = Map("a" -> 12, "b" -> 5, "hello" -> 3)
    println(map1)
    println(map1.getClass)
    //Map(a -> 12, b -> 5, hello -> 3)
    //class scala.collection.immutable.Map$Map3

    //2. 遍历元素
    map1.foreach(println)
    //map1.foreach( (kv: (String, Int)) => println(kv) )
    //(a,12)
    //(b,5)
    //(hello,3)

    //3. 取map中所有的 key 或 value
    for (key <- map1.keys) {
      println(s"$key ---> ${map1.get(key)}")
    }
    //a ---> Some(12)
    //b ---> Some(5)
    //hello ---> Some(3)

    //4. 访问某一个key的value
    println(map1.get("a").get)  //12
    println(map1.get("c"))      //None
    println(map1.getOrElse("c", 0)) //防止为空时get抛出异常   若为None返回0
    //0
  }
}
  1. 可变Map
package com.yu.chapter07

import scala.collection.mutable


object test_MutableMap {
  def main(args: Array[String]): Unit = {
    //1. 创建Map
    val map1 = mutable.Map("a" -> 12, "b" -> 5, "hello" -> 3)
    println(map1)
    println(map1.getClass)
    //HashMap(a -> 12, b -> 5, hello -> 3)
    //class scala.collection.mutable.HashMap

    //2. 添加元素
    map1.put("c", 4)
    map1.put("d", 8)
    println(map1)
    //HashMap(a -> 12, b -> 5, c -> 4, hello -> 3, d -> 8)
    map1 += (("e", 4))

    //3. 删除元素
    map1.remove("a")
    println(map1)  //HashMap(b -> 5, c -> 4, d -> 8, e -> 4, hello -> 3)
    map1 -= "hello"
    println(map1)  //HashMap(b -> 5, c -> 4, d -> 8, e -> 4)

    //4. 修改元素
    map1("a") = 2  //未出现的相当于添加
    map1("b") = 4  //修改
    println(map1)  //HashMap(a -> 2, b -> 4, c -> 4, d -> 8, e -> 4)

    //5. 合并Map
    val map2 = mutable.Map("d" -> 12, "b" -> 99, "k" -> 3)
    map1 ++= map2
    println(map1)  //HashMap(a -> 2, b -> 99, c -> 4, d -> 12, e -> 4, k -> 3)
    //map2中的元素添加到map1中,未出现过的直接添加,出现过的覆盖
    //不可变集合也可以与可变集合合并,但要赋值给新的不可变map
  }
}

7.6 元组

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。

(1)注意:元组中最大只能有 22 个元素。
(2)声明元组的方式:(元素 1,元素 2,元素 3)

package com.yu.chapter07

object test_Tuple {
  def main(args: Array[String]): Unit = {
    //1. 创建元组
    val tuple: (String, Char, Int, Boolean) = ("hello", 'a',  12, false) //类型需要一一对应
    println(tuple) //(hello,a,12,false)

    //2. 访问数据
    println(tuple._1) //hello
    println(tuple._2) //a
    println(tuple._3) //12

    println(tuple.productElement(1))  //返回相应索引位置的元素

    //3. 遍历元组
    for (elem <- tuple.productIterator) {println(elem)}  //依次打印

    //4. 嵌套元组
    val mulTuple = (12, 0.9, (9, "h"), 20)
    println(mulTuple._3)
    //(9,h)
  }
}

7.7 集合常用函数

  1. 基本属性和常用操作

(1)获取集合长度
(2)获取集合大小
(3)循环遍历
(4)迭代器
(5)生成字符串
(6)是否包含

package com.yu.chapter07

object test_CommonOp {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 6, 34)
    val set = Set(23, 45, 1, 77)
//    (1)获取集合长度
    println(list.length)  //4
//    (2)获取集合大小
    println(set.size)     //4
//    (3)循环遍历
    for (elem <- list) {
      println(elem)
    }
    set.foreach(println)
//    (4)迭代器
    for (elem <- set.iterator) println(elem)
//    (5)生成字符串
    println(list)  //List(1, 2, 6, 34)
    println(set)   //Set(23, 45, 1, 77)
    println(list.mkString("--"))   //1--2--6--34
    //    (6)是否包含
    println(list.contains(2))  //true
    println(set.contains(3))   //false
  }
}
  1. 衍生集合
package com.yu.chapter07

object test_DerivedCollection {
  def main(args: Array[String]): Unit = {
    val list1 = List(1, 2, 6, 34, 99)
    val list2 = List(33, 2, 65, 34, 78)
    //    (1)获取集合的头
    println(list1.head)   //1
    //    (2)获取集合的尾(不是头的就是尾) 得到的是新的list,只去除了第一个值
    println(list1.tail)   //List(2, 6, 34, 99)
    //    (3)集合最后一个数据
    println(list1.last)   //99
    //    (4)集合初始数据(不包含最后一个)
    println(list1.init)  //List(1, 2, 6, 34)
    //    (5)反转
    println(list1.reverse)  //List(99, 34, 6, 2, 1)
    //    (6)取前(后)n 个元素
    println(list1.take(3))  //前n个
    println(list1.takeRight(3)) //后m个
    //    (7)去掉前(后)n 个元素
    println(list1.drop(1))   //去掉前n个
    println(list2.dropRight(1))  //去掉后n个
    //    (8)并集
    val union = list1.union(list2)
    println("union " + union)
    println(list1 ::: list2)
    //union List(1, 2, 6, 34, 99, 33, 2, 65, 34, 78)
    //List(1, 2, 6, 34, 99, 33, 2, 65, 34, 78)
    //set合并会去重 set1.union(set2) set1 ++ set2
    //    (9)交集
    val intersection = list1.intersect(list2)
    println("intersection " + intersection)
    //intersection List(2, 34)
    //    (10)差集
    val diff1 = list1.diff(list2)
    val diff2 = list2.diff(list1)
    println("diff1 " + diff1)
    println("diff2 " + diff2)
    //diff1 List(1, 6, 99)
    //diff2 List(33, 65, 78)
    //    (11)拉链
    println(list1.zip(list2)) //一一对应形成二元组,多余的不输出
    //List((1,33), (2,2), (6,65), (34,34), (99,78))
    //    (12)滑窗
    println(list1.sliding(3).foreach(println))
    //List(1, 2, 6)
    //List(2, 6, 34)
    //List(6, 34, 99)
    //()
    println(list1.sliding(3, 2).foreach(println))  //窗口长度,步长
    //窗口长度和步长相同就形成了滚动窗口
    //List(1, 2, 6)
    //List(6, 34, 99)
    //()
  }
}
  1. 集合计算简单函数
package com.yu.chapter07

object test_SimpleFunction {
  def main(args: Array[String]): Unit = {
    val list = List(21, 4, 65, 2, -7)
    val list2 = List(("a", 3), ("b", 1), ("d", 9), ("f", 10))
    //    (1)求和
    println(list.sum)
    //    (2)求乘积
    println(list.product)
    //    (3)最大值
    println(list.max)
    println(list2.max) //(f,10)  默认按元组的第一个元素去取最大
    println(list2.maxBy((tuple: (String, Int)) => tuple._2)) //(f,10)  指定按第二个元素排序
    println(list2.maxBy( _._2) ) //(f,10)
    //    (4)最小值
    println(list.min)
    println(list2.minBy(_._2))
    //    (5)排序
    //5.1 sorted
    val sortedList = list.sorted
    println(sortedList)   //List(-7, 2, 4, 21, 65)
    //从大到小排列 list.sorted.reverse
    //使用隐式参数
    println(list.sorted(Ordering[Int].reverse))
    println(list2.sorted)  //按第一个元素

    //5.2 sortBy
    println(list2.sortBy(_._2)) //List((b,1), (a,3), (d,9), (f,10))
    println(list2.sortBy(_._2)(Ordering[Int].reverse)) //List((f,10), (d,9), (a,3), (b,1))

    //5.3 sortWith
    println(list.sortWith( (a: Int, b: Int) => {a < b}))  //从小打到排序
    println(list.sortWith( _ < _ )) //从小到大排序
    println(list.sortWith(( _ > _))) //从大到小排序
  }
}
  1. 集合计算高级函数

(1)过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化
(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group)
按照指定的规则对集合的元素进行分组
(6)简化(归约)
(7)折叠

package com.yu.chapter07

object test_HighLevalFunction {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, 5, 6, 7, 8)

    //1. 过滤
    //选取偶数
    val evenList = list.filter( (elem: Int) => {elem % 2 == 0} )
    println(evenList)   //List(2, 4, 6, 8)
    println(list.filter( _ % 2== 1)) //选取奇数

    //2. map
    //集合每个数乘2
    println(list.map( _ * 2))  //List(2, 4, 6, 8, 10, 12, 14, 16)
    println(list.map( x => x * x))  //两个相同的x不可省略

    //3. 扁平化
    val nestedList: List[List[Int]] = List(List(1,2,3), List(4,5,6), List(7,8,9))
    val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
    println(flatList)  //List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val flatList2 = nestedList.flatten
    println(flatList2) //List(1, 2, 3, 4, 5, 6, 7, 8, 9)

    //4. 扁平映射
    val wordList: List[String] = List("hello world", "hello scala", "hello java")
    val splitList: List[Array[String]] = wordList.map( _.split(" "))
    val flattenList = splitList.flatten
    println(flattenList) //List(hello, world, hello, scala, hello, java)

    val flatMapList = wordList.flatMap(_.split(" "))
    println(flatMapList) //List(hello, world, hello, scala, hello, java)

    //5. 分组groupBy
    //分成奇偶两组
    val groupMap: Map[Int, List[Int]] = list.groupBy( _ % 2 )
    val groupMap2: Map[String, List[Int]] = list.groupBy( data => if (data % 2 == 0) "偶数" else "奇数" )
    println(groupMap) //HashMap(0 -> List(2, 4, 6, 8), 1 -> List(1, 3, 5, 7))
    println(groupMap2) //HashMap(偶数 -> List(2, 4, 6, 8), 奇数 -> List(1, 3, 5, 7))

    //给定一组词汇,按照单词的首字母进行分组
    val wordList2 = List("China", "alice", "cary", "bob", "america", "canada")
    println(wordList2.groupBy( _.charAt(0) )) //按首字母
    //HashMap(a -> List(alice, america), b -> List(bob), C -> List(China), c -> List(cary, canada))
  }
}
package com.yu.chapter07

object test_HighLevalReduce {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4)

    //1. reduce
    println(list.reduce( _ + _))  // 10
    println(list.reduceLeft( _ + _ )) //10
    println(list.reduceRight( _ + _ )) //10
    val list2 = List(3, 4, 5, 8, 10)
    println(list2.reduce( _ -_ )) //3-4-5-8-10 -24
    println(list2.reduceLeft( _ -_ )) // -24  从左向右减
    println(list2.reduceRight(_ - _ )) // 3 - ( 4 - ( 5 - ( 8 - ( 10))) ) = 6 底层是递归调用的

    //2. fold  给定一个初值
    println(list.fold(10)(_ + _)) //10 + 1 + 2 + 3 - 4  20
    println(list.foldLeft(10)(_ - _)) //10 - 1 - 2 - 3 - 4  0
    println(list2.foldRight(11)(_ -_)) // 3 - (4 - (5 - (8 - (10 - 11))))   -5
  }
}
  1. 普通 WordCount 案例

单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果。

package com.yu.chapter07

import scala.collection.mutable

object test_MergeMap {
  def main(args: Array[String]): Unit = {
    val map1 = Map("a" -> 2, "b" -> 4, "c" -> 3)
    val map2 = mutable.Map("a" -> 4, "b" -> 1, "c" -> 2, "d" -> 9)

    val map3 = map1.foldLeft(map2)(  //这里只能用foldLeft 两个不同值进行fold
      (mergedMap, kv) => {   //第一个参数表示合并后的结果,第二个参数是元素
        val key = kv._1
        val value = kv._2
        mergedMap(key) = mergedMap.getOrElse(key, 0) + value  //查找出现过的,加起来
        mergedMap
      }
    )
    println(map3)
    //HashMap(a -> 6, b -> 5, c -> 5, d -> 9)
  }
}

在这里插入图片描述

package com.yu.chapter07

object test_CommonWordCount {
  def main(args: Array[String]): Unit = {
    val stringList: List[String] = List(
      "hello", "hello world", "hello scala", "hello spark from scala", "hello flink from scala")

    //1. 对字符串进行切分,得到一个扁平化列表
//    val wordList1: List[Array[String]] = stringList.map(_.split(" "))
//    val wordList2: List[String] = wordList1.flatten

    var wordList = stringList.flatMap(_.split(" "))
    println(wordList) //List(hello, hello, world, hello, scala, hello, spark, from, scala, hello, flink, from, scala)

    //2. 相同的单词进行分组
    val groupMap: Map[String, List[String]] = wordList.groupBy(word => word) //如果省略只传入一个通配符下划线,编译器容易产生混淆,所以不进行简写
    println(groupMap)
    //HashMap(world -> List(world), flink -> List(flink), spark -> List(spark), hello -> List(hello, hello, hello, hello, hello), scala -> List(scala, scala, scala), from -> List(from, from))

    //3. 统计出现的个数,取每个list的长度
    val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))
    println(countMap)  //HashMap(world -> 1, flink -> 1, spark -> 1, hello -> 5, scala -> 3, from -> 2)

    //4. 根据count值进行排序,需要转换为list
    val sortList: List[(String, Int)] = countMap.toList
      .sortWith((_._2 > _._2))
      .take(3)
    println(sortList)
    //List((hello,5), (scala,3), (from,2))
  }
}
  1. 复杂 WordCount 案例
package com.yu.chapter07

import scala.collection.MapView

object test_ComplexWordCount {
  def main(args: Array[String]): Unit = {
    val tupleList: List[(String, Int)] = List(
      ("hello", 1), ("hello world", 2), ("hello scala", 3), ("hello spark from scala", 1), ("hello flink from scala", 2))

    //思路1:直接展开
    val newStringList: List[String] = tupleList.map(
      kv => {
        (kv._1.trim + " ") * kv._2  //trim 省略指定字符串中的前导和尾随空格
      }
    )
    println(newStringList)
    //List(hello , hello world hello world , hello scala hello scala hello scala , hello spark from scala , hello flink from scala hello flink from scala )
    //下面正常操作
    val wordCountList: List[(String, Int)] = newStringList
      .flatMap(_.split(" "))
      .groupBy(word => word)
      .map(kv => (kv._1, kv._2.length))
      .toList
      .sortBy(_._2)(Ordering[Int].reverse)
      .take(3)
    println(wordCountList) //List((hello,9), (scala,6), (from,3))

    //2.思路2:基于预统计的结果进行转换
    //2.1 将字符串打散为单词,并结合对应的个数包装成二元组
    val preCountList: List[(String, Int)] = tupleList.flatMap(
      tuple => {
        val strings: Array[String] = tuple._1.split(" ")
        strings.map( word => (word, tuple._2))
      }
    )
    println(preCountList)  //每一个单词拆分开对应
    //List((hello,1), (hello,2), (world,2), (hello,3), (scala,3), (hello,1), (spark,1), (from,1), (scala,1), (hello,2), (flink,2), (from,2), (scala,2))

    //2.2 对二元组进行分组,按照单词
    val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy( _._1 )
    println(preCountMap)
    //HashMap(world -> List((world,2)), flink -> List((flink,2)), spark -> List((spark,1)), hello -> List((hello,1), (hello,2), (hello,3), (hello,1), (hello,2)), scala -> List((scala,3), (scala,1), (scala,2)), from -> List((from,1), (from,2)))

    //2.3 叠加每个单词预统计的个数值
    val countMap: MapView[String, Int] = preCountMap.mapValues(
      tupleList => tupleList.map( _._2 ).sum
    )
    println(countMap)

    //2.4 转换成List,排序取前三
    val countList = countMap.toList
      .sortWith( _._2 > _._2)
      .take(3)
    println(countList)
    //List((hello,9), (scala,6), (from,3))
  }
}

7.8 队列

队列的特点是先进先出。进队和出队的方法分别为 enqueue 和 dequeue。

package com.yu.chapter07

import scala.collection.immutable.Queue
import scala.collection.mutable

object test_queue {
  def main(args: Array[String]): Unit = {
    //创建一个可变队列
    val queue: mutable.Queue[String] = new mutable.Queue[String]()
    queue.enqueue("a", "b", "c")
    println(queue)  //Queue(a, b, c)
    println(queue.dequeue()) //a
    println(queue)  //Queue(b, c)

    //创建一个不可变队列
    val queue2: Queue[String] = Queue("a", "b", "c")
    queue2.enqueue("d")
    println(queue2)  //Queue(a, b, c)  并未改变
    val queue3 = queue2.enqueue("d")
    println(queue3)  //Queue(a, b, c, d)
  }
}

7.9 并行集合

Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

package com.yu.chapter07

import scala.collection.immutable

object tets_parallel {
  def main(args: Array[String]): Unit = {
    val result: immutable.IndexedSeq[Long] = (1 to 100).map(
      x => Thread.currentThread.getId
    )
    println(result)
    //Vector(1, 1, 1, ……)

    //并行计算
    val result2: ParSeq[Long] = (1 to 100).par.map(
      x => Thread.currentThread.getId
    )
    println(result2)
    //ParVector(20, 20, 20, 20, 30, ……) 由不同线程执行
  }
}
  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
英文版深入理解Scala。 本书由Scala之父作序推荐,深入探讨了Scala里几个较为复杂的领域,包括类型系统的高阶内容、隐式转换、特质的组合技巧、集合、Actor、函数式编程的范畴论等,而且不是干巴巴地讲述语言和库的概念。本书示例丰富,是目前为止该领域最好的参考书籍,非常适合有经验的Scala程序员向专家水平进阶的参考读物。本书适合想要了解Scala语言的底层机制和技术细节的读者阅读参考,是学习Scala语言的上上之选择。 Scala是一种多范式的编程语言,它既支持面向对象编程,也支持函数式编程的各种特性。 本书深入探讨了Scala里几个较为复杂的领域,包括类型系统的高阶内容、隐式转换、特质的组合技巧、集合、Actor、函数式编程的范畴论等,而且不是干巴巴地讲述语言和库的概念。本书充满各种实用的建议和最佳实践,可以来帮助读者学习怎样把Scala里较少被掌握的部分应用到工作中。 本书不是Scala的入门级教程,而是适合有经验的Scala程序员向专家水平进阶的参考读物。本书适合想要了解Scala语言的底层机制和技术细节的读者阅读参考。 专业书评 “权威并且易于理解”。——Martin Odersky Scala之父 “带你深入Scala的内部工作机制”。——John C Tyler PROS Pricing “目前为止,我在技术书里读到过的最好的示例”。——Eric Weinberg Wagger Designs “一本开拓眼界的书,现在我对Scala知其所以然了”。——John Criffin Hibernate Search in Action合著者

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值