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) = 10
for(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.bufferAsJavaList
val 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) //访问元素 返回1
val 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))//返回 1
println(m2.getOrElse("D",4))//返回 4
Map 的增删改查
m2("A") = 30 // 若key值存在,则更新value的值;若key值不存在,则添加key-value
m2 += ("D"->40) // 添加元素,若key存在,则更新value
m2 += ("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") // 类型为 Any
set.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)-5
println(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语言---集合的主要内容,如果未能解决你的问题,请参考以下文章