scala 字符串(string)数组(array),映射(Map),元组常用操作

字符串

去除收尾空格

val aaaaa = " 546 "
aaaaa.length = 5
aaaaa.trim().length = 3

去除前缀后缀

val aaaaa = "xxxxx546546yyyyy"
aaaaa.stripPrefix("xxxxx").stripSuffix("yyyyy")

结果:
res1: String = 546546

替换字符串

val aaaaa = "xxxxx546546yyyyy"
aaaaa.replaceAll("xxxxx","yyyyy")

结果:
res2: String = yyyyy546546yyyyy

正则提取

import scala.util.matching.Regex
val pattern = new Regex("[a-zA-Z]+")
pattern.findAllIn(aaaaa).toArray

正则替换
使用字符串自带的replaceALL替换

val a = "aaaaa11111"
a.replaceALL("0","11111")

如果要替换括号"()",需要注意如果只有半个括号,会报错。
如果想只替换半个扩号,那么括号需要用方括号框起来"[]"就能正常运行。

val a = "aaaaa(11111)"
a.replaceALL("aaaaa[(]","")

使用正则表达式中的replaceAllIn

val b = "aaaaa11111"
val regex = "= [A-Za-z]+".r
val newString = regex.replaceAllIn(b, "a")

拼接字符串

val str3 =  str1.concat(str2)

数组

部分转载自:【快学scala】

常用

1.初始化
若长度固定则使用Array,若长度可能有变化则使用ArrayBuffer
1.1. 提供初始值时不要使用new
1.2. 用()来访问元素

  1. map
  2. reduce
val intArray=Array(1,2,3)
intArray.reduce(_+_) //所有元素相加
  1. 用for (elem<-arr)来遍历元素
scala> var intArray=Array(1,2,3)
intArray: Array[Int] = Array(1, 2, 3)

// to  length-1
scala> for(i<- 0 to intArray.length-1){println(intArray(i))}
1
2
3
// until  小于length
scala> for(i<- 0 until intArray.length){println(intArray(i))}
1
2
3
// 正确遍历数组的姿势
scala> for(i<- intArray){println(i)}
1
2
3
//倒叙遍历
scala> for(i<- (0 until intArray.length).reverse){println(intArray(i))}
3
2
1
  1. 用for (elem<-arr if…)…yield…来将原数组转型为新数组
// 生成数组,可以先用ofDim初始化,再往里面填数
scala> val feature_index_array = Array.ofDim[Int](6)
           for (i <- 0 to 5){
               feature_index_array(i)=i;
           }
feature_index_array:Array(0,1, 2, 3, 4, 5)


//  生成新的数组原数组不变  
scala> var intArray=Array(1,2,3)
intArray: Array[Int] = Array(1, 2, 3)

scala> for(i<-intArray) yield i*2
res6: Array[Int] = Array(2, 4, 6)

scala> intArray
res7: Array[Int] = Array(1, 2, 3)

scala> var intArray2=for(i<-intArray) yield i*2
intArray2: Array[Int] = Array(2, 4, 6)
// 加入过滤条件
scala> var intArray2=for(i<-intArray if i>2) yield i*2
intArray2: Array[Int] = Array(6)

//转换类型,把array中的字符串类型转化为Int
var StringArray=Array("1","2","3")
StringArray: Array[String] = Array(1, 2, 3)
scala> for(i<-StringArray) yield i.toInt
res8: Array[Int] = Array(1, 2, 3)

//也可以直接使用map
StringArray.map(_.toDouble)
//用map的时候要注意,比如遇见嵌套的Array就需要使用case来处理
//比如array(array("ID:1111","TEL:1233","NAME:ASDF"),array("ID:1221","TEL:1211","NAME:DFAS"))
//我们需要对array中的子数组做处理,比如只取ID项
array = array.map{case Array(x,y,z)=>Array(x)}

  1. Scala数组和java数组可以互操作;用ArrayBuffer,使用scalacollection.JavaConversions中的转换函数
  2. 如果数组在rdd中,假设结构为(id,array),若想要打印rdd内容并看到数组内容可以a.take(10).foreach(v => println(v._1, v._2.mkString(",")))
  3. -def isEmpty: Boolean 判断当前数组是否为空。
 val a = Array(1, 2, 3, 4, 5)
 a.isEmpty // return false
  1. 交集&差集
    -def intersect(that: collection.Seq[T]): Array[T] 取两个集合的交集
    -def diff(that: collection.Seq[T]): Array[T] 取两个集合的差集
    val a = Array(1, 2, 3, 4, 5)
    val b = Array(3, 4, 6)
    val c = a.intersect(b)//也可以这样 val c = c intersect b
    println(c.mkString(","))    //return 3,4


val a = Array(1, 2, 3,4)
val b = Array(4, 5,6,7)
val c = a.diff(b) //a diff b
println(c.mkString) //1,2,3

10.其他

//求和
scala> intArray.sum
res8: Int = 6
//求最小值
scala> intArray.min
res9: Int = 1
//求最大值
scala> intArray.max
res10: Int = 3
// make String
scala> intArray.mkString(",")
res11: String = 1,2,3
scala> intArray.mkString("<",",",">")
res12: String = <1,2,3>

val first = intArray(0) // 读取第一个元素
intArray(3) = 100 // 替换第四个元素为100
  1. 有时候会出现错误:scala.MatchError: [Ljava.lang.String;@51443799 (of class [Ljava.lang.String;)
    这是Array中元素和调用时元素不匹配造成的,用case时常会遇见这种问题,几种方法可以预防。
    问题重现:
scala> val Array(k, v) = "1,2".split(",")
k: String = 1
v: String = 2
scala> val Array(k, v) = "1,2,3".split(",")
scala.MatchError: [Ljava.lang.String;@508dec2b (of class [Ljava.lang.String;)

11.1. 可以加入if来判断数组是否为空,或者直接判断数组长度
11.2.可以使用_*来代替后续的元素

val Array(k, v, _*) = Array(1, 2, 3, 4, 5)
#k: Int = 1
#v: Int = 2
  1. 生成数组
1.Array.ofDim[Double](3,4) //生成3*4的二维数组,初始值为0.0
2.Array.ofDim[Double](3) //生成length=3的数组,初始值为0.0
3.Array.emptyDoubleArray() //生成一个泛型为double的空数组

用fill创建和填充数组

scala> val array1 = Array.fill(3)("0")
array1: Array[String] = Array("0","0", "0")

13.合并数组
用Array中的concat可以合并数组元素

import Array._
val array = Array.concat(array1,array2,array3)

14.比较数组
判断两个数组是否相等
Array("1","2")==Array("1","2") 是false。
Array("1","2").equal(Array("1","2")) 是false。
需要使用sameElements
Array("1","2") sameElements Array("1","2") 是true
scala中array比较特殊,转成序列或者列表会好一些。
例如:

List("1","2") == List("1","2")    //true
List("1","2") sameElement List("1","2")   //true

如果想知道两个数组(a,b)是否是b被a包含的关系,可以使用相交再相等的方式

val a =  Array("1","2","3").
val b = Array("1","2")
val c = a.intersect(b)     //a = Array("1","2")
c sameElement b       //true

15.查找元素
使用find可以查找符合条件的第一个元素
比如嵌套的数组中array(array("x","y","z"),array("a","b","c"),array("a","w","e")……)
查找数组中子数组第一个元素等于"a"的第一个子数组

array.find({x:Array[String] => x(0) == "a"})

查找出来的结果是Option类型,Some(……),这种类型里的数据不能直接拿出来用,需要用到get方法取值

array.find({x:Array[String] => x(0) == "a"}).get.mkString(",")

使用get,如果查找不到会报以下的错误,并返回一个空字符串。
Spark--java.util.NoSuchElementException: None.get at at
单条这种情况,最后也有返回值,影响不是很大,但是如果是在dataframe中遍历的时候,每条都报这个错误,最后程序就无法运行。所以通常不用get,使用getOrElse,查找不到就返回自己设定的一个值,后面如果不需要,可以手动过滤掉。

array.find({x:Array[String] => x(0) == "a"}).getOrElse(Array("error")).mkString(",")

1.定长数组

val nums = new Array[Int](10)//所有元素初始化为0
//nums: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
val a = new Array[String](10) 
// 10个元素的字符串数组,所有元素初始化为null
//a: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)
val s = Array("Hello","World")
// 长度为2的Array[String]——类型是推断出来的,已提供初始值就不需要new了
//s: Array[String] = Array(Hello, World)

s(0) = "Goodbye"
//Array("Goodbye","World")
//使用()而不是[]来访问元素

2.变长数组:数组缓冲

对于长度需要变化的数组,Java有ArrayList,C++有Vector,Scala中有ArrayBuffer

import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
//或者val b = new ArrayBuffer[Int]()
//一个空的数组缓冲,准备存放数组

b += 1
//ArrayBuffer(1),用 += 在尾端添加元素

b += (1, 2, 3, 5)
// ArrayBuffer(1, 1, 2, 3, 5)
//在尾端添加多个元素,以括号包起来

b ++= Array(8, 13, 21)
//ArrayBuffer(1,1,2,3,5,8,13,21)
// 可以用 ++= 操作符追加任何集合
//但是不能 b++= 1 【错误】1不是集合类型

b.trimEnd(5)
//移除最后5个元素
//ArrayBuffer(1,1,2)

在ArrayBuffer的尾端添加或移除元素是一个高效的操作(”amortized constant time“,固定时间)。
在任意位置插入或移除元素时,效率较低——在那位置之后的元素都要被平移。如:

b.insert(2,6)//在第二个元素后插入6
//ArrayBuffer(1,1,6,2)
b.insert(2,7,8,9) //在第二个元素有插入7,8,9
//ArrayBuffer(1,1,7,8,9,6,2)
b.remove(2)  //移除第二个元素后的一个元素
//ArrayBuffer(1,1,8,9,6,2)
b.remove(2,3) //移除第二个元素后的三个元素
//ArrayBuffer(1,1,2)
//第二个参数是要移除多少元素

3.Array和ArrayBuffer的转换

b.toArray
//Array(1,1,2)
b.toBuffer
//ArrayBuffer(1,1,2)

4.遍历Array和ArrayBuffer

在Java和C++中,数组和数组列表/向量有一些语法上的不同,Scala则更加统一。大多数时候,可以用相同的代码处理这两种数据结构。

for(i <- 0 until a.length)
    println(i + ":" +a(i))
//until返回所有小于但不包括上限的数字。

0 until (a.length, 2)
//Range(0,2,4,...)

(0 until a.length).reverse
//Range(...,2,1,0)

for(elem <- a)
    println(elem)

5.数组转换

从一个数组(或数组转换)出发,以某种方式对它进行转换,这些转换动作不会修改原始数组,而是产生一个全新的数组。

val a = Array(2,3,5,7,11)
val result = for(elem <- a) yield 2*elem
//result是Array(4,6,10,14,22)

val result1 = for(elem <- 0 until 100) yield 2*elem
//scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6, 8, 10, ……,198)
for(elem <- a if elem % 2 == 0) yield 2* elem
//对每个偶数元素翻倍,并丢弃奇数元素

一种等价方法

a.filter(_ % 2 == 0).map(2 * _)
//或者
a.filter{_ % 2 == 0}map{ 2 * _}

高效数组操作

//给定一个整数的数组缓冲,移除第一个负数之外的所有负数。
var first=true
var n=a.length
var i=0
while ( i<n ) {
  if (a(i) >= 0)
    i+=1
  else{
  if (first) {
    first=false
    i+=1
 } else {
a.remove (i)
n-=1 }}}
//从数组缓冲中移除元素并不高效,把非负数值拷贝到前端比较好
var first = true
val indexes = 
for(i<-0 until a.length if first || a(i) >= 0)
    yield{
    if (a(i) < 0) first = false;//遇到第一个负数时置first = false,以后再遇到负数,根据 first||a(i)>=0 就直接跳过了
    i //i是下标
    }
for (j <- 0 until indexes.length) a(j) = a(indexes(j))
    a.trimEnd(a.length - indexes.length)

这里的关键点是,拿到所有下标好过逐个处理,一次就能处理完。

数组转成映射(array转Map)

假设一个场景,一个array中全是字符串,我们需要拿出最长的那个字符串,那么我们可以把这个array转成Map,
映射表中为(str -> str.length)这种形式。
那么我们可以先用case转化array为元祖,再用toMap转化成映射。

val a = Array("1222","733232","2435345", "9568678")
 val b = a.map{case x => (x,x.length) } 
val c = b.toMap
val d = c.maxBy(_._2)
val e = d._1

6.常用算法

求和与排序

求和与排序,Scala有内建的函数来处理这些任务

Array(1,7,2, 9).sum // 19,对ArrayBuffer同样适用

要使用sum方法,元素类型必须是数值类型:要么是整型,要么是浮点数或者Biglnteger/BigDecimal。
同理,min和max输出数组或数组缓冲中最小和最大的元素。

ArraryBuffer("Mary", "had","a","little", "lamb").max // "little"

sorted方法将数组或数组缓冲排序并返回经过排序的数组或数组缓冲,这个过程并不会修改原始版本:

val b=ArrayBuffer(1,7,2, 9)
val bSorted=b.sorted(_ < _) // b没有被改变,bSorted是ArrayBuffer(1,2,7,9)

sortWith方法:

val bDescending = b.sortWith(_>_)  //ArrayBuffeer(9,7,2,1)

可以直接对一个数组排序,但不能对数组缓冲排序:

val a=Array(1,7,2,9)
scala.util.Sorting.quickSortIa(a) // a现在是Array(1,2,7,9)

显示数组内容
最后,如果你想要显示数组或数组缓冲的内容,可以用mkString方法,它允许你指定元素之间的分隔符。该方法的另一个重载版本可以让你指定前缀和后缀。例如:

a.mkString("and") // "1 and 2 and 7 and 9"
a.mkString("<" , "," , ">") // "<1,2,7,9>"

和toString相比:
a.toString // " [I@85b8d",这里被调用的是Java的毫无意义的toString方法
b.toString // "ArrayBuffer(l,7,2, 9)",toString方法报告了类型,便于调试

7.多维数组

多维数组是通过数组的数组来实现的。举例来说,Double的二维数组类型为:
Array[Array[Double]]
要构造这样一个数组,可以用ofDim方法:

val matrix=Array.ofDim[Double](3,4) //三行,四列要访问其中的元素,使用两对圆括号:
matrix (row) (column) =42

你可以创建不规则的数组,每一行的长度各不相同:

val triangle=new ArraylArray [Int] (10)
for (i <- 0 until triangle.length)
triangle(i)=new Array[lnt] (i+1)

8.转化

scala中的容器大部分可以使用toListtoSettoArraytoMap等相互转换
如果要转化成java容器,例如scala List转java List

import scala.collection.JavaConverters._
scalaList.asJava

9.随机采样

import scala.util.Random
Random.shuffle(df_host_array.toList).take(10)

映射

构造映射

映射是键/值对偶的集合。Scala有一个通用的叫法-元组-n个对象的聚集,并不一定要相同的类型。对偶不过是一个n=2的元组。我们可以通过以下方式构造映射,如

1.构造不可变映射

val map = Map("a" -> 1, "b" -> 2)
map: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)

注:上述代码构造了一个不可变的Map[String, Int]-对偶类型Scala会自动推导,其值不能被改变。你可以通过 -> 操作符来创建对偶。你也可以通过Map(("a", 1), ("b", 2))来创建对偶。

2.构建可变映射

val res = scala.collection.mutable.Map("a" -> 1, "b" -> 2)
res: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1)

注:上述代码构建了一个可变的Map[String, Int],其值可以被改变。Scala可以推导出Map对偶的类型,但是如果为Map(),则会生成一个可变的Map[Nothing, Nothing]。

3.构建空映射

val res = new scala.collection.mutable.HashMap[String, Int]
res: scala.collection.mutable.HashMap[String,Int] = Map()

val res: collection.mutable.Map[String, Double] = collection.mutable.Map()
res: scala.collection.mutable.HashMap[String,Double] = Map()

注:上述代码构建了一个可变空映射。

获取映射中的值

在Scala中,你要使用()表示法来查找某个键对应的值。如,

scala> val map = scala.collection.mutable.Map("a" -> "b", "b" -> "a")
map: scala.collection.mutable.Map[String,String] = Map(b -> b, a -> a)
 
scala> map("a")
res0: String = b

注:如果映射并不包含请求中使用的键,则会抛出异常。如果你要检查映射中是否包含某个指定的键,可用contains方法。映射中有一个getOrElse方法,有则取对应key值,否则取默认值,如.getOrElse("c", "t"),调用返回字符串t。在Scala中,映射.get(键)这样的调用返回一个Option对象,要么是Some(键对应的值),要么是None。

getOrElse()主要就是防范措施,如果有值,那就可以得到这个值,如果没有就会得到一个默认值,getOrElse()方法要比用get()方法安全得多。

object Test5 {
  def main(args: Array[String]): Unit = {
    var map=Map[Int,String]()
    map+=(1->"one",2->"two")
    println(map.getOrElse(1,"default"))
    println(map.getOrElse(2,"default"))
    println(map.getOrElse(3,"default"))
  }
}

结果

one
two
default

4 更新映射中的值

在可变映射中,你可以更新某个映射的值,或者添加一个新的映射关系,
1.更新/新增一个键/值对,做法是在=号的左侧使用()

scala> val map = scala.collection.mutable.Map("a" -> "a", "b" -> "b")
map: scala.collection.mutable.Map[String,String] = Map(b -> b, a -> a)
 
scala> map("a") = "a1"
 
scala> map("c") = "c"
 
scala> print(map("a") + "-" + map("c"))
a1-c

1.1 也可以用update方法
map1.update(new_key, new_value)

2.添加多个键/值对,使用+=

scala> val map = scala.collection.mutable.Map("a" -> "a", "b" -> "b")
map: scala.collection.mutable.Map[String,String] = Map(b -> b, a -> a)
 
scala> map += ("c" -> "c", "d" -> "d")
res4: map.type = Map(b -> b, d -> d, a -> a, c -> c)

3.移除某个键和对应的值,使用-=

scala> val map = scala.collection.mutable.Map("a" -> "a", "b" -> "b")
map: scala.collection.mutable.Map[String,String] = Map(b -> b, a -> a)
 
scala> map -= "b"
res5: map.type = Map(a -> a)

在不可变映射中,你不可以更新其值。但你仍然可以对其进行操作,如
1.获取一个包含所需要的更新的映射,使用+

scala> val map = Map("a" -> "a", "b" -> "b")
map: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b)
 
scala> val newMap = map + ("b" -> "b1", "c" -> "c")
newMap: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b1, c -> c)

注:newMap映射包含了与map相同的映射关系,此外"c"被添加进来,"b"被更新。在不变映射中,老的和新的映射共享大部分数据结构。
2.移除不可变映射中某个键,使用-

scala> var map = Map("a" -> "a", "b" -> "b")
map: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b)
 
scala> map = map + ("b" -> "b1", "c" -> "c")
map: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b1, c -> c)
 
scala> map = map - "c"
map: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b1)

注:不变映射中,老的和新的映射共享大部分数据结构。

5 迭代映射

如果你想迭代映射,可使用如下结构,即for((k, v) <- 映射) 处理k和v,如

scala> var map = Map("a" -> "a", "b" -> "b")
map: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b)
 
scala> for((k, v) <- map) println("key: " + k + ", value: " + v)
key: a, value: a
key: b, value: b

注:如果你想迭代key,则可使用for(k <- map.keySet) ...,如果你想迭代value,则可使用for(v <- map.values) ...,如果你想反转一个映射,则可使用for((k, v) <- 映射) yield (v, k)。

6 合并映射(添加新元素)

直接合并用```++``即可。
合并映射,相同的key,value相加

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
val map2 = Map("key2" -> 4, "key3" -> 6, "key5" -> 10)
val res = map1 ++ map2.map(t => t._1 -> (t._2 + map1.getOrElse(t._1, 0)))
println(res)

合并映射小例子

xs是一个数组,里面是字符串,字符串格式前面是用户id后面是召回的id。
希望把s1,s1,s3合并,如果多次命中就把相应的召回id相乘,只保留一个。
val s1 = "11474647:2,11238255:2"
val s2 = "10001309:3,11238255:3,10038251:3"
val s3 = "10199662:7"
val xs = Array(s1,s2,s3)

    var res = new scala.collection.mutable.HashMap[String, Int]
    for (s <- xs) {
//先把array中的元素转成映射
      val m = s.toString.split(",").map(x => {
        (x.split(":")(0).toString, x.split(":")(1).toInt)
      }).toMap
//把元素转换的多个映射合并
//getOrElse如果没有召回id就设为1,相乘没有变化。
      res = res ++ m.map(t => t._1 -> (t._2 * res.getOrElse(t._1, 1)))
    }

7 可变Map和不可变Map相互转换

1、mutable.Map to immutable.Map

val map = mutable.Map(1 -> "zhangsan", 2 -> "lisi")
val result = map.toMap

2、immutable.Map to mutable.Map

val map = immutable.Map(1 -> "zhangsan", 2 -> "lisi")
val result = mutable.Map(map.toSeq: _*)

8 collectAsMap

scala> val data = sc.parallelize(List((1, "www"), (1, "iteblog"), (1, "com"), 
    (2, "bbs"), (2, "iteblog"), (2, "com"), (3, "good")))
data: org.apache.spark.rdd.RDD[(Int, String)] =
    ParallelCollectionRDD[26] at parallelize at <console>:12
 
scala> data.collectAsMap
res28: scala.collection.Map[Int,String] = Map(2 -> com, 1 -> com, 3 -> good)

从结果我们可以看出,如果RDD中同一个Key中存在多个Value,那么后面的Value将会把前面的Value覆盖,最终得到的结果就是Key唯一,而且对应一个Value。

注意:

映射的一些方法在udf或map中会报错。
java.io.NotSerializableException: scala.collection.immutable.MapLike$$filterKeys$2
原因是在使用mapvalue方法时产生了一个无法序列化的对象。
MapLike中的方法比如mapvalue/filterKeys之类的无法序列化,需要加
map(identity)
比如说udf中出现了filterKeys来剔除异常值,到这一步udf直接返回result_map,数据是可以出来的,但是如果下面再对result_map是用map等需要分发的操作,就会报错,这是spark的一个bug。
在result_map后面加上.map(identity),就正常了。
网上也有说加上.map(x=>x)效果一样,我试了一下没成功,可能场景不完全相同。

    val result_map=res.toMap.filterKeys(x=>{
      x !=("1000")
    }).map(identity)
...
...

附:Map表的大部分操作

搬运来自:https://blog.csdn.net/xianpanjia4616/article/details/80947616
默认使用不可变的Map

package test
 
/**
  * map的操作;
  */
object MapDemo {
  def main(args: Array[String]): Unit = {
    var map = Map[String,String]("name" -> "jason","age" -> "500","test_100" -> "test_100","test_101" -> "test_101") //引用可变,支持读写操作;
    map += ("city" -> "北京")  //新增
    println(map)  //打印结果为:Map(city -> 北京, name -> jason, test_100 -> test_100, test_101 -> test_101, age -> 500);
    val map2 = Map[String,String]("sex" -> "男","brand" -> "apple") //引用不可变,只能第一次写入值,之后只能读取;
    //map2 += ("test" -> "报错吗")  //此时不能加,直接报错;
    val map3 = scala.collection.mutable.Map[String,String]()   //引用不可变,支持读写操作;
    map3 += ("test" -> "能添加吗")  //添加单个元素;
    map3 += ("test" -> "改变了") //更新;
    map3 += ("success" -> "添加成功了吗","anthor" -> "另外一个")  //添加多个元素;
    println(map3)  //打印结果为:Map(success -> 添加成功了吗, anthor -> 另外一个, test -> 能添加吗);
    println(map3.keys)  //返回所有的key;
    println(map3.values)//返回所有的value;
    println(map3.isEmpty) //当map为空时,返回true;
    var combine_map = map ++ map2  //合并两个map;
    println(combine_map) //打印结果为:Map(city -> 北京, name -> jason, test_100 -> test_100, test_101 -> test_101, age -> 500, brand -> apple, sex -> 男);
    combine_map -= ("city","name") //删除指定的key;
    println(combine_map)  //打印结果为:Map(test_100 -> test_100, test_101 -> test_101, age -> 500, brand -> apple, sex -> 男)
    println(combine_map.get("age").get)  //返回指定key的值;
    println(combine_map.init) //返回所有元素,除了最后一个;
    println(combine_map.last) //返回最后一个元素;
    println(combine_map.max)  //查找最大元素;
    println(combine_map.min)  //查找最小元素;
    println(combine_map.mkString("")) //集合所有元素作为字符串显示;
    //println(combine_map.product) //返回集合中数字元素的积;注意得是num型;
    println(combine_map.size)  //返回map的大小;
    println(combine_map.toArray) //集合转数组;
    println(combine_map.toBuffer) //返回缓冲区,包含了Map的所有元素;
    println(combine_map.toList) //返回List,包含了Map的所有元素;
    combine_map.get("test_101").getOrElse("不存在") //根据key取value值,如果不存在返回后面的值;
    val keySet = combine_map.keys
    val key_iter = keySet.iterator  //遍历,迭代map;
    while (key_iter.hasNext){
      val key = key_iter.next
      println(key + ":" + combine_map.get(key).get)
    }
    println(combine_map.apply("brand")) //返回指定键的值,如果不存在返回 Map 的默认方法;
    println(combine_map.contains("test_key")) //如果map中存在指定 key,返回 true,否则返回 false;
    val age_count = combine_map.count(x=>{  //计算满足指定条件的集合元素数量;
      x._1.equals("age")
    })
    println(age_count) //打印结果为1;
    val drop_map = combine_map.drop(1) //返回丢弃最后n个元素新集合;
    println(drop_map) //打印结果为:Map(brand -> apple, sex -> 男);
    println(combine_map.empty) //返回相同类型的空map;
    println(map.equals(map2)) //如果两个 Map 相等(key/value 均相等),返回true,否则返回false;
    println(combine_map.exists(x => { //判断集合中指定条件的元素是否存在;
      x._2.equals("男")
    }))
    println(combine_map.filter(x=>{  //返回满足指定条件的所有集合; 结果为:Map(brand -> apple);
      x._1.length > 4
    }))
    println(combine_map.filterKeys(x=>{ //返回符合指定条件的不可变 Map;
      x.equals("test_100")
    }))
    println(combine_map.find(x=>{  //查找集合中满足指定条件的第一个元素;
      x._1.equals(x._2)
    }))
    combine_map.foreach(x=>{   //循环map里的所有元素;
      println(x +"------------")
    })
 
  }
}

元组

映射是键/值对偶的集合。对偶是元组(tuple)的最简单形态--元组是不同类型值的聚集。元组的值是通过将单个的值包含在圆括号中构成的。如,(1, 2.66, "lm")是一个元组类型为Tuple3[Int, Double, java.lang.String]的三元数组,元组类型也可写为(Int, Double, java.lang.String)。

scala> val tuple = (1, 2.66, "lm")
tuple: (Int, Double, String) = (1,2.66,lm)

1.通过_下标获取元组的值

scala> val tuple = (1, 2.66, "lm")
tuple: (Int, Double, String) = (1,2.66,lm)
 
scala> print(tuple._1)
1

注:你可以使用变量._下标 获取值,也可用变量 _下标获取值。十分注意的是,和数组或字符串中的位置不同,元组的各组元从1开始,而非0。
2.使用匹配模式获取元组的值

scala> val tuple = (1, 2.66, "lm")
tuple: (Int, Double, String) = (1,2.66,lm)
 
scala> val (first, second, thrid) = tuple
first: Int = 1
second: Double = 2.66
thrid: String = lm

注:如果并不是所有的元素都需要,那么你可以在不需要的元素位置上使用_,如val(first, second, _),则下标为3的值不会被返回。元组可用于函数需要返回不止一个值的情况。

拉链操作

拉链操作,即把多个值绑定在一起,以便他们能够被一起处理,这可以使用zip方法来完成,如

scala> val arr1 = Array("<", "-", ">")
arr1: Array[String] = Array(<, -, >)
 
scala> val arr2 = Array(2, 10, 2)
arr2: Array[Int] = Array(2, 10, 2)
 
scala> val pairs = arr1.zip(arr2)
pairs: Array[(String, Int)] = Array((<,2), (-,10), (>,2))
 
scala> for((s, n) <- pairs) print(s * n)
<<---------->>

注:可以使用toMap方法将对偶转换成映射,即arr1.zip(arr2).toMap。

在开发过程中,通常使用元组的场景比较单一,一般就是整合成(key,value)这样配合reducebykey,swap之类的方法使用,比如最简单的单词计数再排序。

rdd.flatMap(line => line.split(" "))
.map(word => (word, 1)) //使用map把rdd中元素改成元祖再计数
.reducebykey(_ + _)
.map { pair => pair.swap }  //或者map(_.swap)
.sortByKey(true, 2).top(3).foreach(println)

Reference

【快学scala】
https://stackoverflow.com/questions/41093240/scala-matcherror-ljava-lang-string-of-class-ljava-lang-string
https://blog.csdn.net/kanaka10/article/details/82878474
https://blog.csdn.net/xianpanjia4616/article/details/80947616

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,417评论 1 24
  • 数组是一种可变的、可索引的数据集合。在Scala中用Array[T]的形式来表示Java中的数组形式 T[]。 v...
    时待吾阅读 938评论 0 0
  • 少年壮志不言愁劝君惜取少年时 定长数组: Scala使用Array表示长度不变的数组scala> val nums...
    xhades阅读 624评论 0 0
  • 可变和不可变集合 Scala中的集合可分为可变集合和不可变集合。可变集合可以当场被更新,不可变集合本身是不可变的。...
    liqing151阅读 200评论 0 0
  • 原标题关于登记房产协助执行的分析 房屋登记部门在实践工作中经常会需要配合法院办理各种登记,比如协助查封,协助执行。...
    小好阅读 525评论 1 2