scala语言---集合

Posted LongRangerTing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala语言---集合相关的知识,希望对你有一定的参考价值。

1. scala集合基本介绍

1) scala集合同时支持不可变集合可变集合,不可变集合可以安全的并发访问

两个包:  不可变集合   scala.collection.immutable

               可变集合       scala.collection.mutable

2)scala默认采用不可变集合,对于几乎所有的集合类,scala同时提供可变和不可变版本。

3)scala集合有3大类:序列seq、集set、映射Map,所有的集合都扩展自Iterable。

4)scala不可变集合继承关系图

注:IndexSeq和LinearSeq的区别----IndexSeq通过索引查找和定位,速度快。LinearSeq是线性的,即有头有尾,一般通过遍历来查找。

2.定长数组

//方式一val arr1 = new Array[Int](10) //10个元素额数组                               //[Int] 表示泛型arr1(1) = 7 //集合元素采用小括号()访问for(i <- arr1)  //数组元素遍历  或 数组下标的方式遍历 println(i)//方式二val arr2 = Array(1,2,3,4) //定义数组时,直接赋值(使用apply方法创建数组对象)val arr3 = Array(1,2,3,"Herry") //arr3的类型为 Any
for(i <- 1 to 10) // [1,10]for(i <- 1 until 10)   // [1,10)

3. 变长数组

//增删改查import scala.collection.mutable._ //导包val arr1 = new ArrayBuffer[Int]()    //创建arr1.append(7)   //追加元素                  //每append一次,arr1在底层会重新分配空间,进行扩容,arr1的地址也会发生变化arr1(0) = 9 //修改元素arr1.remove(1)   //删除数组下标为 1 的元素

变长数组与定长数组的转换

arr.toBuffer  //定长数组转可变数组arr.toArray   //可变数组转定长数组,其返回结果是定长数组 而arr本身没变化

4. 二维数组

val arr = Array.ofDim[Double](3,4)//二维数组中有3个一维数组,每个一维数组中有4个元素arr(1)(1) = 10for(item <- arr){ for(it <- item){ print(it + "\t") } println()}//二维数组的遍历for(i <- 0 to arr.length - 1){    for(j <- 0 to arr(i).length - 1){        printf("arr[%d][%d] = %d\t",i,j,arr(i)(j))    }}

5. scala集合和Java集合互相转换

val arr = ArrayBuffer("1","2","3")import scala.collection.JavaConversions.bufferAsJavaListval javaArr = new ProcessBuilder(arr)val arrList = javaArr.command()println(arrList)

6. 元祖

可以理解为一个容器,可以存放各种类型(相同或不同)的数据。

访问元祖中的数据可以采用顺序号(_.顺序号),也可以通过索引(productElement)访问

val t = (1,2,3,"hello")t._2    //返回2    方式一t.productElement(0) //返回 1 方式二

元祖的遍历

var t1 = (1,"a","b",true,2)for(item <- t1.productIterator){ println(item)}

List

val aa = List(1,2,3,"hello")aa(0) //访问元素 返回1val bb = Nil //空集合aa :+ 44 //在列表的最后面加元素 返回List(1,2,3,"hello",44)44 +: aa //在列表的最前面加元素 返回List(44,1,2,3,"hello")

Map

是一个散列表,存储的内容是键值对(key-value)映射,scala中不可变的map是有序的,可变的map是无序的。

val m1 = Map[String,Int]()val m2 = Map((1,200),(2,300))val m3 = Map("hello"->1,"Hery"->3,"Bob"->10)val m4:Map[String,Int] = Map(("hello",20),("ketty",30))val m = Map("hello"->10,"merr"->20,"Ketty"->"Beijing") //类型Map[String,Any]val m5 = mutable.Map(("A",1),("B",2),("C",3))

1) 取元素

map(key) 取出元素,key值存在返回value;key值不存在,抛异常

val m3 = Map("hello"->1,"Hery"->3,"Bob"->10)val a = m3("hello")  // map(key) 取出元素,key值存在返回value;key值不存在,抛异常

2)使用contains方法检查是否存在key

若key存在,返回true,若key不存在,返回false。

if(m3.contains("hello"))    println("key存在 值 = "+m3("hello))

3)使用map.get(key).get取值

通过map.get(key)返回一个Option对象,要么是Some,要么是None

val m2 = Map(("A",1),("B","BeiJing"),("C",3)) println(m2.get("B"))// 返回值 Som(BeiJing) println(m2.get("B").get)// 返回值 BeiJing

4)使用map.getOrElse()取值

key值存在,返回key对应的值;key不存在,返回默认值

val m2 = Map(("A",1),("B","BeiJing"),("C",3))println(m2.getOrElse("A",4))//返回 1println(m2.getOrElse("D",4))//返回 4

Map 的增删改查

m2("A") = 30   // 若key值存在,则更新value的值;若key值不存在,则添加key-valuem2 += ("D"->40)   // 添加元素,若key存在,则更新valuem2 += ("D"->4,"E"->32)  // 添加多个元素 m2 -= ("D","A")  //删除 多个元素

 Map的遍历

对map的元素(元祖Tuple2对象)进行遍历

val m2 = Map(("A",1),("B","BeiJing"),("C",3))for((k,v) <- m2){ println(k+" is map to "+v)for(k <- m2.keys) //打印key值 println(k)for(v <- m2.values) //打印value值 printlnl(v)for(kv <- m2) //打印 Tuple2 println(kv)

‍‍Set

不重复元素的集合,默认创建不可变集合

val set = Set(1,2,3,"D")   // 类型为 Anyset.add(45) //添加元素set += 90 //添加元素set += (100,200) //添加元素set -= 100        //删除元素set.remove(90) //删除元素

7. 集合(seq、set、map)元素的映射---map映射操作

需求:将list(2,5,7)中的所有元素都乘以2,将其结果放到一个新的集合中返回,即返回新的list(4,10,14)

上面提出的问题,其实就是一个关于集合元素映射操作的问题。在scala中可以通过map映射来解决:将集合中的每一个元素通过指定的功能(函数)映射(转换)成新的结果集合,其实就是将函数作为参数传递给另外一个函数。这就是函数式编程的特点。

def map[B](f:(A) => B):HashSet[B]// 说明:1)[B] 是泛型//       2) map是一个高阶函数//       3)HashSet就是返回的新的集合
def sum(a:Int):Int = { a + a}// test 高阶函数// f:Int => Int 表示一个函数,入参为一个Int类型,返回值为 Int//  n1:Int  普通参数def test(f:Int => Int, n1:Int){ f(n1)}// 调用  test(sum,2)  返回值为 4// 调用  test(sum _,2)
def myPrint():Unit = { println("hello world")}val f1 = myPrint _ //在scala中,可以把一个函数直接赋值给一个变量,但是不执行函数f1() //执行函数
def say()={println("OK----")}//test2是一个高阶函数,可以接受一个 没有输入,返回值为Unit的函数def test2(f:()=>Unit)={ f()}//调用test2(say)
val ll2 = List(1,2,3)def multiMap(a:Int):Int = {   a *100}   // multiMap 调用3次val ll3 = ll2.map(multiMap)//List的每个元素都会传递给multiMap函数
//需求:将单词全部转换成大写def upper(s:String):String = {    s.toUpperCase}val names = List("Alice","Bob","Nick")val name2 = names.map(upper)
def main(args:Array[String]):Unit = { val list1 = List(1,3,5,7)    def f1(n1:Int): Int = {     println("XXX")     2 * n1    }    val list2 = list1.map(f1)    println(list2)}//  上述代码的模拟实现def main(args:Array[String]):Unit = { val myList = MyList() val myList2 = myList.map(f1)    println("myList2 = " + myList2)    println("myList = " + myList.list1)}class MyList{ var list1 = List(1,3,5,7) var list2 = List[Int]()    def map(f:Int => Int):List[Int] = {     for(item <- list1){     list2 = list2 :+ f(item)     }     list2    }}object MyList{ def apply():MyList = new MyList()}

flatmap映射

def main(args:Array[String]):Unit = { val names = List("Alice","Bob","Nick")    val name2 = names.flatMap(upper)    //name2 为 List(A,L,I,C,E,B,O,B,N,I,C,K)}def upper(s:String):String = { s.toUpperCase}

filter过滤

def main(args:Array[String]):Unit = { val names = List("Alice","Bob","Nick") val name2 = names.filter(startA) //name2 为 List("Alice")}def startA(str:String):Boolean = {    str.startsWith("A")}

化简:将二元函数引用于集合中的函数

def reduceLeft(B >: A)(@deprecatedName('f) op:(B,A) => B):B// reduceLeft(f) 接收的函数需要的形式为 op:(B,A) => B):B// reduceLeft(f) 运行规则是 从左边开始执行将得到的结果返回给第一个参数,然后继续和下一个元素// 运行,将得到的结果继续返回给第一个参数,继续运行// 即 ((((1+2)+3)+4)+5) = 15
val list = List(1,20,30,4,5)def sum(n1:Int,n2:Int):Int = { n1 + n2}val res = list.reduceLeft(sum)println("res = " + res)

reduceLeft(_+_)  这个函数的执行逻辑:

val list = List(1,2,3,4,5)def minus(n1:Int,n2:Int):Int = { n1 - n2}println(list.reduceLeft(minus))//结果为 -13  (((1-2)-3)-4)-5println(list.reduceRight(minus))//结果为 3 1-(2-(3-(4-5)))println(list.reduce(minus))// 默认为reduceLeft

折叠

fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中所以元素被遍历

val list = List(1,2,3,4)def minus(n1:Int,n2:Int):Int = { n1 - n2}//理解成 List(5,1,2,3,4) list.reduceLeft(minus)println(list.foldLeft(5)(minus))//  (((5-1)-2)-3)-4//理解成 List(1,2,3,4,5) list.reduceRight(minus)println(list.foldRight(5)(minus))// 1-(2-(3-(4-5)))

foldLeft 和 foldRight 缩写方式 分别是  /:  和  :\

val list = List(1,2,3,4)def minus(n1:Int,n2:Int):Int = { n1 - n2}var i2 = (1 /: list)(minus) //等价 list.foldLeft(1)(minus)var i3 = (list :\ 10)(minus) // 等价 list.foldRight(10)(minus)






以上是关于scala语言---集合的主要内容,如果未能解决你的问题,请参考以下文章

scala语言---集合

Scala语言之数据集合

为什么Scala是可扩展的?

2021年大数据常用语言Scala(二十一):函数式编程 遍历 foreach

详解 Scala 模式匹配

scala语言-循环