集合
简介
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。
可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。而不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变,所以这里的不可变并不是变量本身的值不可变,而是变量指向的那个内存地址不可变
可变集合和不可变集合,在scala中该如何进行区分呢?我们一般可以根据集合所在包名进行区分:
scala.collection.immutable
scala.collection.mutable
//TODO 集合 -java /* * List:存储有序,可重复 * ArrayList&LinkedList * Set:存储无序,数据不可重复 * HashSet & TreeSet * Map:存储KV键值对,KEY是不能重复的,VALUE是可以重复的,存储无序 * HashMap & Hashtable & TreeMap * java是一个面向对象的语言,所以学习集合的时候,更侧重数据之间的关系,以及数据结构之间的关系 * Scala是一个面向函数式的语言,所以学习集合的时候,更侧重集合本身的功能 * Scala集合主要分为三大类: *序列Seq:存储有序,可重复 * 集Set:存储无序,数据不可重复 * 映射Map:存储KV键值对,KEY是不能重复的,VALUE是可以重复的,存储无序 * ********************************************************************************** * String & StringBuilder * String不可变字符串,因为类没有提供改变其内容的方法,如果有,是创建新的字符串 * SttringBuilder可变字符串,很多方法就是改变其自身的内容 * Scala中集合分为两大类: * 不可变集合 & 可变集合 * 原始数据:处理数据时,一般要从数据源获取数据,但是数据源的数据一般不能被改变的 * 如果必须改变,也是创建的新的数据 * */
数组
不可变数组
1) 基本语法
//java中数据不算是集合 //java中的集合都是有自己类型的 ArrayList<String> /* * String[] strs=new String[3]; * */ //scala是一个完全面向对象的语言,所以万物皆对象 //数组也是对象,也有自己的类型:Array //scala中Array的本质就是java的数组[]
public class TestArray { public static void main(String[] args) { String[] strs=new String[3]; //修改数据 strs[0]="zhangsan"; strs[1]="lisi"; strs[2]="wangwu"; System.out.println(strs); } }
数组基本操作
package 集合 object Scala01_Collection_Array { def main(args: Array[String]): Unit = { //TODO 集合 --数组 //java中数据不算是集合 //java中的集合都是有自己类型的 ArrayList<String> /* * String[] strs=new String[3]; * */ //scala是一个完全面向对象的语言,所以万物皆对象 //数组也是对象,也有自己的类型:Array //scala中Array的本质就是java的数组[] //scala中的中括号表示泛型 //scala => Array => [Ljava.lang.String;@11531931 //java => Strng[] => [Ljava.lang.String;@11531931 //TODO 数组的基本操作 //创建 val array=new Array[String](3) //增删改查 //Array没有添加和删除的能力,只能通过索引的方式修改数据 //Array访问时的索引操作采用小括号,而不是中括号 array(0)="zhangsan" //查询数组的数据,可以通过索引的方式 println(array(0)) array(1)="lisi" array(2)="wangwu" println(array) println(array.length) //可以直接将数组中的数据生成字符串 println(array.mkString(", ")) //可以采用基本的for循环的方式 for (str<-array){ println(str) } //scala之间采用面向对象的方式实现循环操作:foreach //foreach方法的作用就是将集合中的每一条数据进行操作 //这里的处理逻辑不是固定的,由开发人员自行决定,scala集合帮开发人员将数据传递到逻辑 //foreach方法的参数有一个,这个参数类型是函数类型:String=>Unit def foreachFunction(str:String):Unit={ println("***********"+str) } //将函数对象作为参数使用时,参数名称很重要,但是函数的名称不重要,所以一般情况下可以简化 //对象.方法() // array.foreach(foreachFunction) array.foreach((str:String)=>{ println("**************"+str) }) //自简原则 array.foreach(str => println("**************" + str) ) array.foreach(println(_)) //array.foreach(println) } }
package 集合 object Scala02_Collection_Array { def main(args: Array[String]): Unit = { //TODO 集合- 数组 //构建数组 //String[] strs=new String[]{"1","2","3"} //集合在构建时,希望同时增加数据,而不是构建后再增加 //此时可以采用集合对象的特殊方法:apply val array: Array[Int] = Array.apply(1, 2, 3, 4) //apply方法可以被scala编译器自动识别的,可以省略 val array1: Array[Int] = Array(1, 2, 3, 4) println(array.mkString(", ")) println(array1.mkString(", ")) //TODO Array其实是不可变数组 val array2=Array(1,2,3,4) //添加数据,会产生新的数据 val arr1: Array[Int] = array.+:(5) val ints: Array[Int] = array.:+(6) array.foreach(println) println(array eq arr1) //false println(array eq ints) //false //一般情况下,调用集合对象的特殊符号的方法时,都会采用运算符方式来使用 //如果运算符采用冒号结尾,那么运算规则为从右向左计算 val array5=array :+6 val array7=5+:array println(array5.mkString(", ")) //1, 2, 3, 4, 6 println(array7.mkString(", ")) //5, 1, 2, 3, 4 val array8=array5 ++:array7 println(array8.mkString(",")) //1,2,3,4,6,5,1,2,3,4 } }
package 集合 object Scala03_Collection_Array { def main(args: Array[String]): Unit = { //多维数组=>数组中有数组 val myMatrix: Array[Array[Int]] = Array.ofDim[Int](3, 3) // myMatrix.foreach(list=>println(list.mkString(","))) myMatrix.foreach(list=>list.foreach(println)) // 合并数组 val arr1=Array(1,2,3,4) val arr2=Array(5,6,7,8) val arr6: Array[Int] = Array.concat(arr1, arr2) arr6.foreach(println) // 创建指定范围的数组 val arr7: Array[Int] = Array.range(0, 2) arr7.foreach(println) // 创建并填充指定数量的数组 val arr8: Array[Int] = Array.fill[Int](5)(-1) arr8.foreach(println) } }
可变数组
1) 基本语法
package 集合 import scala.collection.mutable.ArrayBuffer object Scala03_Collection_ArrayBuffer { def main(args: Array[String]): Unit = { //TODO 集合 -可变数组 val buffer = new ArrayBuffer[Int] // 增加数据 buffer.append(1, 2, 3, 4) // 修改数据 buffer.update(0, 5) buffer(1) = 6 // 删除数据 val i: Int = buffer.remove(2) buffer.remove(2, 2) // 查询数据 println(buffer(3)) // 循环集合 for (i <- buffer) { println(i) } } }
package 集合 import scala.collection.mutable.ArrayBuffer object Scala04_Collection_ArrayBuffer { def main(args: Array[String]): Unit = { val buffer1 = ArrayBuffer(1, 2, 3, 4) val buffer2 = ArrayBuffer(5, 6, 7, 8) val buffer3: ArrayBuffer[Int] = buffer1 += 5 println(buffer1 eq buffer3) // true // 使用 ++ 运算符会产生新的集合数组 val buffer4: ArrayBuffer[Int] = buffer1 ++ buffer2 // 使用 ++= 运算符会更新之前的集合,不会产生新的数组 val buffer5: ArrayBuffer[Int] = buffer1 ++= buffer2 println(buffer1 eq buffer4) // false println(buffer1 eq buffer5) // true } }
可变数组和不可变数组转换
package 集合 import scala.collection.mutable import scala.collection.mutable.ArrayBuffer object Scala06_Collection_ArrayBuffer { def main(args: Array[String]): Unit = { val buffer = ArrayBuffer(1, 2, 3, 4) val array = Array(4, 5, 6, 7) // 将不可变数组转换为可变数组 val buffer1: mutable.Buffer[Int] = array.toBuffer // 将可变数组转换为不可变数组 val array1: Array[Int] = buffer.toArray } }
package com.atguigu; import java.util.ArrayList; import java.util.List; public class TestCollect { public static void main(String[] args) { List<Integer> nums=new ArrayList<Integer>(); nums.add(1); nums.add(2); nums.add(3); //TODO 原始数据想要把每条数据乘以2,产生新的集合(不可变) //TODO 原始数据想要把每条数据乘以2,产生新的集合(可变) for(int i=0;i<nums.size();i++){ Integer num = nums.get(i); nums.set(i,num*2); } System.out.println(nums); List<Integer> newmuti = newmuti(nums); // nums.set() //修改 // nums.get() //获取 muti(nums); } //TODO 原始数据想要把每条数据乘以2,产生新的集合(可变) public static List<Integer> newmuti(List<Integer> nums){ ArrayList<Integer> num2 = new ArrayList<>(); for(Integer num:num2){ num2.add(num*2); } return num2; } public static void muti(List<Integer> nums){ for (int i=0;i<nums.size();i++){ Integer num=nums.get(i); nums.set(i,num*2); } } }
Seq集合
不可变List
1) 基本语法
package 集合 object Scala01_Collection_Seq { def main(args: Array[String]): Unit = { //TODO 集合 -Seq(序列) //scala集合中的Seq表示是有序,数据可以重复的数据集合 //TODO 构建 //1.seq集合需要指定泛型 //type JavaHashMap =java.util.HashMap[String,String] //Seq是一个trait,所以无法直接构建对象,一般采用伴生对象的apply方法 //val seq=new Seq[Int]() //Seq是一个trait,无法直接构建对象,所以底层采用的是List集合 val seq:Seq[Int]=Seq.apply(1,2,3,4) var list=List(1,2,3,4) //相等的写法 //TODO 增删改查 println(seq) }
package 集合 object Scala02_Collection_Seq { def main(args: Array[String]): Unit = { //TODO -Seq(序列) -List //seq所表示的有序的概念,说的就是数据的插入顺序,不是大小顺序 //val list:List[Int] =List(1,4,3,2) //seq所表示的数据可重复的概念 //val list:List[Int]=List(1,1,1,1) //println(list) //TODO 基本数据操作 //Seq,List集合默认使用时是不可变的,所以常用的数据操作方法其实都是特殊符号 val list1=List(1,2,3,4) val list2=List(5,6,7,8) //list1.:(5) //list1.+:(6) //list1.++:(list2) val list3=list1 :+5 val list4=5+:list1 println(list3 eq list1) println(list1) println(list2) println(list3) println(list4) } }
package 集合 object Scala03_Collection_Seq { def main(args: Array[String]): Unit = { val list1=List(1,2,3,4) val list2=List(5,6,7,8) //使用不同的方式构建集合 //:: 这个运算符表示向集合中添加数据,但是因为以冒号结尾,所以计算的规则从后向前 //如果直接使用List(),表示空集合,向空集合中添加数据比较常见的方式是这种 //为了操作方便,所以可以采用特殊对象来替代空集合:Nil val list3=1::2::3::4::List() val list4=1::2::3::4::Nil val list5=9::list2::list1 val list6=9::list2:::list1 println(list3) println(list4) println(list6) } }
Seq可变集合 & 不可变集合
import scala.collection.mutable import scala.collection.mutable.ListBuffer object Scala05_Collection_Seq { def main(args: Array[String]): Unit = { val buffer = ListBuffer(1, 2, 3, 4) val list = List(5, 6, 7, 8) // 可变集合转变为不可变集合 val list1: List[Int] = buffer.toList // 不可变集合转变为可变集合 val buffer1: mutable.Buffer[Int] = list.toBuffer } }
Set集合
不可变Set
package 集合 object Scala06_Collection_Set_01 { def main(args: Array[String]): Unit = { val set1 = Set(1, 2, 3, 4) val set2 = Set(5, 6, 7, 8) // 增加数据 val set3: Set[Int] = set1 + 5 + 6 val set4: Set[Int] = set1.+(6, 7, 8) println(set1 eq set3) // false println(set1 eq set4) // false // println(set3) // println(set4) // set4.foreach(print) // // 删除数据 val set5: Set[Int] = set1 - 2 - 3 set5.foreach(println) // val set6: Set[Int] = set1 ++ set2 set6.foreach(print) println("********") val set7: Set[Int] = set2 ++: set1 set7.foreach(println) println(set6 eq set7) } }
package 集合 object Scala06_Collection_Set { def main(args: Array[String]): Unit = { //TODO 集合 - Set(集) //set集合描述了无序 ,数据不可重复集合 //TODO 构建 //set是一个trait,不能直接构建对象,而且默认为不可变集合 //一般情况下,集合都采用伴生对象apply方法 val set1=Set(1,2,3,4,5,6,7,8) val set2=Set(1,1,1,1,1) val set3=Set(1,2,3,4) //不可变集合的基本数据操作都是采用特殊符号 val set4=set3+5 println(set1) println(set2) println(set3) println(set4) } }
可变Set
package 集合 import scala.collection.mutable object Scala06_Collection_Set_1 { def main(args: Array[String]): Unit = { //可变的set集合,需要根据包名进行区分 val set1 = mutable.Set(1, 2, 3, 4) val set2 = mutable.Set(5, 6, 7, 8) val set3=mutable.Set(1,1,1,1,1) //TODO 增删改查 //set集合没有append,insert方法的,因为没有顺序的概念 // 增加数据 set2.add(5) // 添加数据:set集合没有位置的位子,所以无法对指定的位置进行修改,所以是数据的状态的修改 set1.update(6, true) println(set1.mkString(",")) set2(6)=true println(set2.mkString(",")) // 删除数据 set1.update(3, false) println(set1.mkString(",")) // 遍历数据 set2.foreach(println) } }
import scala.collection.mutable object Scala06_Collection_Set_02 { def main(args: Array[String]): Unit = { val set1 = mutable.Set(1, 2, 3, 4) val set2 = mutable.Set(4, 5, 6, 7) // 交集 val set3: mutable.Set[Int] = set1 & set2 println(set3.mkString(",")) // 差集 val set4: mutable.Set[Int] = set1 &~ set2 println(set4.mkString(",")) } }
Map集合
Map(映射)是一种可迭代的键值对(key/value)结构。所有的值都可以通过键来获取。Map 中的键都是唯一的。
不可变Map
package 集合 object Scala06_Collection_Map { def main(args: Array[String]): Unit = { //TODO --Map(映射) //Map集合中存储的是K-V键值对数据 //这个数据是无序的,而且K不能重复的,V是可以重复 //可以通过Map中的key关联到Value //Map是一个trait,一般情况下,采用伴生对象的apply方法进行构建,默认为不可变Map集合 //TODO 构建 //scala中kv键值对可以采用特殊的方法构建 val kv="a"->1 val map=Map(kv,"b"->2,"c"->3,"d"->5,"f"->6) val map1=Map("a"->1,"a"->2,"a"->3) //3 会覆盖 //TODO 增删改查 println(map) println(map1) }
package 集合 object Scala06_Collection_Map23 { def main(args: Array[String]): Unit = { val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3) val map2 = Map("d" -> 4, "e" -> 5, "f" -> 6) // 创建空集合 val empty: Map[String, Int] = Map.empty println(empty) // 获取指定key的值 val i: Int = map1.apply("c") println(i) println(map1("c")) // 获取可能存在的key值 val maybeInt: Option[Int] = map1.get("c") // 判断key值是否存在 if (!maybeInt.isEmpty) { // 获取值 println(maybeInt.get) } else { // 如果不存在,获取默认值 println(maybeInt.getOrElse(0)) } // 获取可能存在的key值, 如果不存在就使用默认值 println(map1.getOrElse("c", 0)) } }
可变Map
package 集合 import scala.collection.mutable object Scala06_Collection_Map1 { def main(args: Array[String]): Unit = { //构建可变Map集合 val map= mutable.Map("a"->1,"a"->2,"a"->3) //增删改查 map.put("b",4) map.put("a",4) map.update("b",5) map.update("c",6) map.remove("a") map.clear() map.mkString(",") map.foreach(println) println(map) val iterator: Iterator[String] = map.keysIterator val iterator1: Iterator[Int] = map.valuesIterator } }
集合之间的转化
package 集合 import scala.collection.mutable object Scala06_Collection_Map22 { def main(args: Array[String]): Unit = { val map1 = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3) val map2 = mutable.Map("d" -> 4, "e" -> 5, "f" -> 6) val set: Set[(String, Int)] = map1.toSet val list: List[(String, Int)] = map1.toList val seq: Seq[(String, Int)] = map1.toSeq val array: Array[(String, Int)] = map1.toArray println(set.mkString(",")) println(list.mkString(",")) println(seq.mkString(",")) println(array.mkString(",")) println(map1.get("a")) println(map1.getOrElse("a", 0)) println(map1.keys) println(map1.keySet) println(map1.keysIterator) println(map1.values) println(map1.valuesIterator) } }
Map--KV键值对 & Option类型
package 集合 import scala.collection.mutable object Scala06_Collection_Map2 { def main(args: Array[String]): Unit = { //TODO Map(关联,映射) //构建可变Map集合 val map= mutable.Map("a"->1,"a"->2,"a"->3) //TODO 按照key获取v //获取的结果类型为Option类型,表示选项类型,这个类型只有两个对象可以选择 //Some:有值 如果有值,那么可以获取真实结果 //None:无值 如果没值,如果获取,会发生错误 //这里之所以采用新的类型获取结果,主要原因是为了避免空指针异常 val maybeInt: Option[Int] = map.get("a") if(maybeInt.isEmpty){ println("没有获取结果") }else{ println("获取的结果为: "+maybeInt.get) } //Option可以在获取不到数据时,提供默认值,需要采用方法:getOrElse println(maybeInt.getOrElse(0)) //Map集合为了操作方便,也提供了类似于getOrElse的方法 val result=map.getOrElse("d",0) println(result) } }
元组
在Scala语言中,我们可以将多个无关的数据元素封装为一个整体,这个整体我们称之为:元素组合,简称元组。有时也可将元组看成容纳元素的容器,其中最多只能容纳22个
package 集合 //tuple介绍 class Scala08_Collection_Tuple { def main(args: Array[String]): Unit = { //集合就是容器,可以容纳数据 /* * 如果想要让无关的数据作为整体来使用: * 1.如果数据之间有关系,一般生成Bean对象,对应其属性 * 2.如果数据类型,含义相同,一般使用集合:Set,Seq[Any],Array[Any] * 3.Scala语言采用特殊的方式将无关数据(元素)作为整体,组合在一起,称为[元组] * 元祖在scala中是一个特殊的集合,采用小括号声明,将数据包含到小括号中即可 * 元祖也是集合,所以有类型:TupleN[Classtype...] * */ val t:Tuple3[Int,String,Int]=(1,"zhangsan",30) } class User{ var id:Int= _ var name:String=_ var age:Int=_ } }
package 集合 object Scala08_Collection_Tuple1 { def main(args: Array[String]): Unit = { //tuple如果采用集合类型来表示,比较麻烦,可以采用简化版本 val t:Tuple3[Int,String,Int]=(1,"zhangsan",30) // 创建元组,使用小括号 val t1:(Int,String,Int)=(1,"zhangsan",30) // 根据顺序号访问元组的数据 //无法使用循环操作,因为数据之间没有关系,就不能采用相同的循环逻辑 println(t1._1) println(t1._2) println(t1._3) // 迭代器 val iterator: Iterator[Any] =t1.productIterator // 根据索引访问元素 t1.productElement(0) // 获取整体 println(t1) // 如果元组的元素只有两个,那么我们称之为对偶元组,也称之为键值对 val kv: (String, Int) = ("a", 1) val kv1: (String, Int) = "a" -> 1 //1->2->3->4 //((1,2),3,4) println(kv eq kv1) //TODO Map集合的操作有变化 val map=Map( ("a",1),("b",2),("c",3) ) //println(map) for(kv <-map){ println(kv._1+"="+kv._2) } } }
字符串处理的小练习
package 集合 object Scala08_Collection_Test { def main(args: Array[String]): Unit = { //TODo 将给定的字符串,首写字母变成大写字母返回 //zhangsan =>Zhangsan //lisi => Lisi // println(firstToUpper("sunyujie")) println(firstToUpper("")) } def firstToUpper(str:String):String={ // str.substring(0,1).toUpperCase+str.substring(1) val opt: Option[String] = Option(str) if(opt.isEmpty){ opt.getOrElse("") }else{ val value:String=opt.get if(value.trim.length==0){ "" }else if(value.trim.length==1){ value.substring(0,1).toUpperCase }else if(value.trim.length>1){ value.substring(0,1).toUpperCase+value.substring(1) }else{ "" } } } }
常用方法
package 集合 object Scala_Collection_Method { def main(args: Array[String]): Unit = { //集合通用方法 val list = List(1, 2, 3, 4) // 集合长度 println("size =>" + list.size) println("length =>" + list.length) // 判断集合是否为空 println("isEmpty =>" + list.isEmpty) // 集合迭代器 println("iterator =>" + list.iterator) // 循环遍历集合 list.foreach(println) // 将集合转换为字符串 println("mkString =>" + list.mkString(",")) // 判断集合中是否包含某个元素 println("contains =>" + list.contains(2)) // 取集合的前几个元素 println("take =>" + list.take(2)) // 查找元素 println("find =>" + list.find(x => x % 2 == 0)) // 丢弃前几个元素 println("drop =>" + list.drop(2)) // 丢弃后几个元素 println("dropRight =>" + list.dropRight(2)) // 反转集合 println("reverse =>" + list.reverse) // 去重 println("distinct =>" + list.distinct) } }
衍生集合
package 集合 object Scala_Collection_Method_1 { def main(args: Array[String]): Unit = { val list = List(1, 2, 3, 4) val list1 = List(3, 4, 5, 6) val list2=List(1,2,3,4,5,6) // 集合头 println("head => " + list.head) // 集合尾 println("tail => " + list.tail) // 集合尾迭代 println("tails => " + list.tails) // 集合初始化 println("init => " + list.init) // 集合初始化迭代 println("inits => " + list.inits) // 集合最后元素 println("last => " + list.last) // 集合并集 println("union => " + list.union(list1)) // 集合交集 println("intersect => " + list.intersect(list1)) // 集合差集 println("diff => " + list.diff(list1)) // 切分集合 println("splitAt => " + list.splitAt(2)) // 滑动 //sloding方法可以将集合中一部分固定数量的数据作为整体进行数据处理 //将整个整体的数据范围称为窗口,而这个窗口跟随计算进行滑动,称为滑动窗口 println("sliding => " + list.sliding(2)) val value: Iterator[List[Int]] = list2.sliding(2) while (value.hasNext){ println(value.next()) } // 滚动 println("sliding => " + list.sliding(2, 2)) // 拉链:将两个数据拉在一起 println("zip => " + list.zip(list1)) // 数据索引拉链 println("zipWithIndex => " + list.zipWithIndex) } }
功能函数
map
map: 集合映射,将集合通过指定的转换规则转换成新的集合
//TODO map方法就是用于数据集中的每一条数据进行转换处理,获取转化后新的数据集
//List=>(map)logic=>List
package 集合 import scala.collection.mutable.ListBuffer object Scala_Collection_Method_2 { def main(args: Array[String]): Unit = { val list=List(1,2,3,4) //List(2,4,6,8) //List(3,6,9,12) //想要实现一个不确定的功能,但是这个功能的目的是将数据集中的每一条数据进行处理后返回新的集合,但是这个处理逻辑是不确定的 //List=>logic=>List def test(num:Int)={ num*3 } // println(transform(list, test)) println(transform(list, _*3 )) //TODO map方法就是用于数据集中的每一条数据进行转换处理,获取转化后新的数据集 //List=>(map)logic=>List println(list.map(_*3)) } def transform(list:List[Int],f:(Int)=>Int):List[Int]={ val newlist=ListBuffer[Int]() //动态添加 list.foreach( num=>{ val result:Int=f(num) newlist.append(result) } ) newlist.toList //返回集合 } }
package 集合 import scala.collection.mutable.ListBuffer object Scala_Collection_Method_3 { def main(args: Array[String]): Unit = { //map:将数据集中的每一条数据按照指定的逻辑进行转化,获取新的集合 val list=List(1,2,3,4) val list1=ListBuffer(1,2,3,4) //可变 //map方法需要传递一个参数,这个参数的类型为函数类型:Int => B //这里的Int表示数据集中的每一条数据,B为处理后的结果,但是类型任意 def fun(num: Int):Int={ num*2 } // val value: List[Int] = list.map(fun) // println(list1.map(fun)) // println(value) // list.map((num:Int)=>{ // num*2 // }) //TODO 当匿名函数只有一个参数,且每个数据都要进行处理时,就可以在匿名函数中使用下划线 //这里的下划线就是每一条数据 println(list.map(_ * 2)) } }
扁平化
flatten: 集合扁平化,所谓的扁平化就是将整体拆分成一个一个的个体
package 集合 object Scala_Collection_Method_4 { def main(args: Array[String]): Unit = { //TODO 集合 val list=List( List(1,2,3),List(3,4,6) ) println(list.size) //TODO //flatten: 集合扁平化,所谓的扁平化就是将整体拆分成一个一个的个体 //List(1,2,3,4)=>1,2,3,4 val newlist: List[Int] = list.flatten println(newlist.size) val list1=List( "Hello Scala","Hello Hadoop" ) //这里的flatten方法会将字符串当做char数组,所以扁平化后,就是一个一个的char val newlist1: List[Char] = list1.flatten println(newlist1) //List(H, e, l, l, o, , S, c, a, l, a, H, e, l, l, o, , H, a, d, o, o, p) //如果想要实现自定义的扁平化操作,一般采用一个功能函数 //flatMap可以实现自定义的扁平化操作 //1=>N //TODO flatMap方法需要传递一个参数,参数类型为函数类型:String=> IterableOnce //这里的String其实就是数据集中的每一条数据 //这里的 IterableOnce其实就是集合类型的顶层通用类型,意味着任何集合都可以此处使用 val newlist2: List[String] = list1.flatMap( str => { str.split(" ") } ) val newlist2: List[String] = list1.flatMap( _.split(" ") ) println(newlist2) } }
filter过滤
filter: 集合过滤数据,按照指定的规则对集合中的每条数据进行筛选过滤,满足条件的保留
//,不满足条件的丢弃
package 集合 object Scala_Collection_Method_45 { def main(args: Array[String]): Unit = { //filter: 集合过滤数据,按照指定的规则对集合中的每条数据进行筛选过滤,满足条件的保留 //,不满足条件的丢弃 //fiter方法需要传递一个参数,这个参数的类型为函数类型Int=>Boolean val list=List(1,2,3,4) val newlist: List[Int] = list.filter(num => false) println(newlist) //TODO 保留数据集中的奇数 val newlist1: List[Int] = list.filter( // num => { // num % 2 != 0 // } _%2!=0 ) println(newlist1) } }
分组goupBy
package 集合 object Scala_Collection_Method_groupBy { def main(args: Array[String]): Unit = { /* groupBy: 集合分组数据 , 按照指定的规则对集合中的每个数据进行分组 , 指定的规则其实就*/ // 是一个函数,这个函数返回的结果就是分组的 key. val list: List[Int] = List(1, 2, 3, 4) //TODO grupBy方法需要传递一个参数,这个参数的类型为函数类型:Int=>K //Int表示数据集中的每一个数据 //K 表示数据分组的标记,执行操作后,相同的标记会在一起 //groupBy方法执行结果会返回Map集合 //Map集合中的key表示分组的标记,value表示相同标记的数据集合 val stringtoInts: Map[String, List[Int]] = list.groupBy( num => { if (num % 2 == 0) { "偶数" } else { "奇数" } } ) println(stringtoInts) // list.groupBy(num=>{ // num%2 // }) list.groupBy(_%2) } }
mapValues
package 集合 object Scala_Collection_Method_mapValues { def main(args: Array[String]): Unit = { val datamap: Map[String, Int] = Map( ("a", 1), ("b", 2), ("c", 3) ) //(a,2)(b,4)(c,6) //map方法可以将数据集中得每一条数据转化为新的数据,放置在新的集合中 //A=>B //A=>map=>B //_代表标占位符,一个代表一个参数 val newlist: Map[String, Int] = datamap.map( kv => { // val k = kv._1 // val v = kv._2 // // (k, v * 2) (kv._1,kv._2*2) } ) println(newlist) //当kv类型得到数据在转化时,k不变,对v进行转化 val newMap1=datamap.mapValues( num=>{ num*2 } ) println(newMap1) } }
sortBy
集合排序,将集合中每个数据按照指定的规则进行排序
package 集合 object Scala_Collection_Method_sortby { def main(args: Array[String]): Unit = { // sortBy: 集合排序,将集合中每个数据按照指定的规则进行排序 val list=List(1,2,3,4,11,12) //sortBy可以传递一个参数,参数类型为函数类型:Int=>B //这里的Int就是数据集中的一条数据 //B就是排序的标记 //sortby按照标记,对数据进行排序 //dortBy默认情况下。是升序排序 val newlist: List[Int] = list.sortBy( num => num.toString //字符串是按字典排序 ) println(newlist) println(newlist.reverse) //TODO sortBy方法存在函数柯里化可以传递多个参数列表 val value: List[Int] = list.sortBy(num => num.toString)(Ordering.String.reverse) println(value) } }
package 集合 object Scala_Collection_Method_sortby1 { def main(args: Array[String]): Unit = { val user1 = new User() val user2 = new User() val user3 = new User() user1.age=20 user2.age=40 user3.age=30 val list: List[User] = List(user1, user2, user3) val newlist: List[User] = list.sortBy(user => user.age)(Ordering.Int.reverse) println(newlist) } class User{ var age:Int=_ override def toString: String = { s"User[${age}]" } } }
sortWith
package 集合 object Scala_Collection_Method_sortWith { def main(args: Array[String]): Unit = { //sortWith: 自定义排序 // 大 > 小 降序 // 小 < 大 升序 val user1 = new User() val user2 = new User() val user3 = new User() val user4 = new User() user1.age = 20 user2.age = 40 user3.age = 30 user4.age=30 user1.money=1000 user2.money=2000 user3.money=2500 user4.money=1500 val list: List[User] = List(user1, user2, user3,user4) //TODO 先按照年龄排序,相同年龄按照金额排序 // val newlist: List[User] = list.sortBy(user => user.age).sortBy(user=>user.money) //sortWith: 自定义排序,只是告诉集合排序的维度.但是具体数据排序过程由集合本身完成 //sortWith方法需要传递一个参数,参数类型为函数类型:(User,User)=>Boolean //这里的User就是集合中用于比较的两个User对象 //Boolean表示预计的排序结果的判断值,true:预想的结果,false:不是预想结果 val newlist: List[User] = list.sortWith((user1, user2) => { // 大 > 小 降序 // 小 < 大 升序 if(user1.age<user2.age){ true }else if (user1.age==user2.age){ user1.money<user2.money } else{ false } }) println(newlist) } class User { var age: Int = _ var money:Int= _ override def toString: String = { s"User[${age},${money}]" } } }
sortBy--元组
package 集合 object Scala_Collection_Method_sortby3 { def main(args: Array[String]): Unit = { //sortWith: 自定义排序 // 大 > 小 降序 // 小 < 大 升序 val user1 = new User() val user2 = new User() val user3 = new User() val user4 = new User() user1.age = 20 user2.age = 40 user3.age = 30 user4.age = 30 user1.money = 1000 user2.money = 2000 user3.money = 2500 user4.money = 1500 val list: List[User] = List(user1, user2, user3, user4) //TODO 如果scala中的排序的规则如下: //先按第一个数据排序,如果数据相同,再按第二个数据排序,如果数据相同,再按第三个排序 //可以采用特殊的方式排序:Tuple排序 val newlist: List[User] = list.sortBy(user => { (user.age, user.money) //默认情况下,sortBy为升序排列,如果想要降序,那么需要传递第二个参数列表 })(Ordering.Tuple2(Ordering.Int,Ordering.Int.reverse)) println(newlist) } class User { var age: Int = _ var money: Int = _ override def toString: String = { s"User[${age},${money}]" } } }
reduce
package 集合 object Scala_Collection_Method_reduce { def main(args: Array[String]): Unit = { //TODO 计算过程中,必须两两计算 //两两计算完毕后,继续执行两两计算,迭代操作 // 所有的数据参与计算后,会得到总的结果 //reduce方法可以实现自定义的聚合计算 //reduce方法需要传递一个参数,参数类型为函数类型:(A1,A1)=>A1 val list=List(1,2,3,4) val result: Int = list.reduce( // (x: Int, y: Int) => { // println(x+"+"+y) // x + y // } _+_ ) //reduce的底层操作是reduceleft val result1: Int = list.reduceLeft(_ - _) val result2: Int = list.reduceRight(_ - _) println(result) //10 println(result1) //-8 println(result2) //-2 } }
fold&scan
package 集合 object Scala_Collection_Method_fold { def main(args: Array[String]): Unit = { //需要将数据集和外部数据进行聚合,这个时候,reduce无法实现,如果想要聚合,可以采用fold var list=List(1,2,3,4) //fold方法存在函数柯里化,有两个参数列表 //第一个参数列表中传递一个参数,计算初始值 //第二个参数中传递一个参数,参数的类型为函数类型,表示计算逻辑:(A1,A1)=>A1 val result: Int = list.fold(5)(_ + _) println(result) //15 val result2: Int = list.foldLeft(5)(_ - _) val redult3: Int = list.foldRight(5)(_ - _) println(result2) //-5 println(redult3) //3 //TODO 扫描的功能 println(list.scan(5)(_ - _)) } }
案例实操 - WordCount TopN
package 集合 import scala.collection.MapView import scala.io.{BufferedSource, Source} object Scala_Collection_Method_WordCount { def main(args: Array[String]): Unit = { //TODO 案例实操 - WordCount TopN /* * TODO 思路梳理: * 1.获取数据源 * 2.判断 * */ //(Hello,4)(World,3),(Scala,2),(Spark,1) //1.获取数据源:.从文件中获取数据: 一行一行的字符串,放置在集合中,那么集合的泛型就是String val source: BufferedSource = Source.fromFile("F:\\scala代码\\data\\word.txt") val dataList: List[String] = source.getLines().toList source.close() // 2.将一行一行的字符串,拆分成一个一个的单词 //将每行数据中的单词分解(拆分)出来,采用扁平化 val wordlist: List[String] = dataList.flatMap( line => { line.split(" ") } ) //3.map方法可以将数据按照指定的规则转化为其他数据,这里的转化可以是类型转化,也可以是数值转化 //A=>B val wordToOneList: List[(String, Int)] = wordlist.map( world => { (world, 1) } ) // println(wordToOneList) //4.统计数据前,先将数据按照规则聚合在一起 //将数据按照指定的规则进行分组:相同的单词放在一起 //groupBy方法会将数据集中的每条数据加分组标记,相同标记的数据放置在一起 //groupBy方法的返回结果就是分组后的Map集合 // Map集合中的key就是分组的标记,value就是相同标记的数据集合 val wordGroup: Map[String, List[(String, Int)]] = wordToOneList.groupBy( kv => { kv._1 } ) //5.将聚合后的数据统计 val worldcount: Map[String, Int] = wordGroup.map( kv => { (kv._1, kv._2.length) } ) println(worldcount) // 6.将统计的结果根据次数排序,取前三名 //分组后的结果为Map类型,Map类型没有顺序,所以无法排序 val top3: List[(String, Int)] = worldcount.toList.sortBy( kv => { kv._2 } )(Ordering.Int.reverse).take(3) println(top3) } }
开发WordCount
package 集合 import scala.io.{BufferedSource, Source} object Scala_Collection_Method_WordCount2 { def main(args: Array[String]): Unit = { val source: BufferedSource = Source.fromFile("F:\\scala代码\\data\\word.txt") val dataList: List[String] = source.getLines().toList source.close() dataList .flatMap( _.split(" ") ).map((_, 1) ).groupBy( _._1 ).map( kv => { (kv._1, kv._2.length) } ).toList.sortBy( _._2 )(Ordering.Int.reverse) .take(3) .foreach(println) } }
另外一种WordCount
package 集合 object Scala_Collection_Method1_WordCount { def main(args: Array[String]): Unit = { val dataList = List( ("Hello Scala World Spark", 4), ("Hello Scala World ", 3), ("Hello World ", 2), ("Hello", 1), ) // ("Hello Scala World Spark", 4) 表示 "Hello Scala" 出现4次 //Hello Scala World SparkHello Scala World SparkHello Scala World SparkHello Scala World Spark //1.将现有的数据转化为熟悉的数据格式 dataList.map( kv=>{ //字符串有乘法的,表示字符串重复出现 (kv._1+" ")*kv._2 } ).flatMap(_.split(" ")) .map((_,1)) .groupBy(_._1) .map(kv=>{ (kv._1,kv._2.length) }).toList.sortBy(_._2)(Ordering.Int.reverse) .take(3) .foreach(println) // .foreach(println) } }
package 集合 //集合可以进行简单计算 // val list1: List[Int] = List(1, 2, 3, 4) // println(list1.sum) // println(list1.max) // println(list1.min) // println(list1.product) //乘集 24 object Scala_Collection_Method_WordCount4 { def main(args: Array[String]): Unit = { val list: List[(String, Int)] = List(("Hello", 1), ("Hello", 2), ("Hell0", 3), ("Hello", 4)) //得到(hello,10) val sum: Int = list.map( // kv => kv._2 _._2 ).sum println(sum) } }
不同省份的商品点击排行
package 集合 import scala.collection.immutable object Scala_Collection_Method_WordCount6 { def main(args: Array[String]): Unit = { val list = List( ("zhangsan", "河北", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "鞋"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "鞋"), ("zhangsan", "河南", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "鞋"), ("zhangsan", "河北", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "帽子"), ("zhangsan", "河南", "鞋"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "电脑"), ("zhangsan", "河南", "鞋"), ("lisi", "河南", "衣服"), ("wangwu", "河南", "电脑"), ("zhangsan", "河南", "电脑"), ("lisi", "河北", "衣服"), ("wangwu", "河北", "帽子") ) //不同省份的商品点击排行 val list1: List[(String, String)] = list.map(num => { (num._2, num._3) }) // println(list1) val list2: Map[String, List[(String, String)]] = list1.groupBy(_._1) // println(list2) val list3: Map[String, Map[String, List[(String, String)]]] = list2.map(num => { (num._1, num._2.groupBy(pro => pro._2)) }) // println(list3) val list4: Map[String, Map[String, Int]] = list3.map(num => { (num._1, num._2.map((kv) => { (kv._1, kv._2.size) })) }) // println(list4) val list5: List[(String, Map[String, Int])] = list4.toList // println(list5) val list6: List[(String, List[(String, Int)])] = list5.map((a) => { (a._1, a._2.toList.sortBy(_._2)(Ordering.Int.reverse)) }) println(list6) } }