scala 字符串(string)數(shù)組(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)

數(shù)組

部分轉(zhuǎn)載自:【快學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
// 正確遍歷數(shù)組的姿勢
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…來將原數(shù)組轉(zhuǎn)型為新數(shù)組
// 生成數(shù)組病游,可以先用ofDim初始化,再往里面填數(shù)
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)


//  生成新的數(shù)組原數(shù)組不變  
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)

//轉(zhuǎn)換類型,把array中的字符串類型轉(zhuǎn)化為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中的子數(shù)組做處理,比如只取ID項
array = array.map{case Array(x,y,z)=>Array(x)}

  1. Scala數(shù)組和java數(shù)組可以互操作耽梅;用ArrayBuffer众旗,使用scalacollection.JavaConversions中的轉(zhuǎn)換函數(shù)
  2. 如果數(shù)組在rdd中,假設結構為(id,array),若想要打印rdd內(nèi)容并看到數(shù)組內(nèi)容可以a.take(10).foreach(v => println(v._1, v._2.mkString(",")))
  3. -def isEmpty: Boolean 判斷當前數(shù)組是否為空。
 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. 有時候會出現(xiàn)錯誤:scala.MatchError: [Ljava.lang.String;@51443799 (of class [Ljava.lang.String;)
    這是Array中元素和調(diào)用時元素不匹配造成的豹悬,用case時常會遇見這種問題,幾種方法可以預防。
    問題重現(xiàn):
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來判斷數(shù)組是否為空,或者直接判斷數(shù)組長度
11.2.可以使用_*來代替后續(xù)的元素

val Array(k, v, _*) = Array(1, 2, 3, 4, 5)
#k: Int = 1
#v: Int = 2
  1. 生成數(shù)組
1.Array.ofDim[Double](3,4) //生成3*4的二維數(shù)組,初始值為0.0
2.Array.ofDim[Double](3) //生成length=3的數(shù)組然遏,初始值為0.0
3.Array.emptyDoubleArray() //生成一個泛型為double的空數(shù)組

用fill創(chuàng)建和填充數(shù)組

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

13.合并數(shù)組
用Array中的concat可以合并數(shù)組元素

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

14.比較數(shù)組
判斷兩個數(shù)組是否相等
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比較特殊斤葱,轉(zhuǎn)成序列或者列表會好一些。
例如:

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

如果想知道兩個數(shù)組(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可以查找符合條件的第一個元素
比如嵌套的數(shù)組中array(array("x","y","z"),array("a","b","c"),array("a","w","e")……)
查找數(shù)組中子數(shù)組第一個元素等于"a"的第一個子數(shù)組

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

查找出來的結果是Option類型慎颗,Some(……)运杭,這種類型里的數(shù)據(jù)不能直接拿出來用,需要用到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.定長數(shù)組

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個元素的字符串數(shù)組掌挚,所有元素初始化為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.變長數(shù)組:數(shù)組緩沖

對于長度需要變化的數(shù)組,Java有ArrayList,C++有Vector,Scala中有ArrayBuffer

import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
//或者val b = new ArrayBuffer[Int]()
//一個空的數(shù)組緩沖,準備存放數(shù)組

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)
//第二個參數(shù)是要移除多少元素

3.Array和ArrayBuffer的轉(zhuǎn)換

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

4.遍歷Array和ArrayBuffer

在Java和C++中,數(shù)組和數(shù)組列表/向量有一些語法上的不同薇宠,Scala則更加統(tǒng)一。大多數(shù)時候拯欧,可以用相同的代碼處理這兩種數(shù)據(jù)結構包各。

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

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

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

for(elem <- a)
    println(elem)

5.數(shù)組轉(zhuǎn)換

從一個數(shù)組(或數(shù)組轉(zhuǎn)換)出發(fā)砚亭,以某種方式對它進行轉(zhuǎn)換,這些轉(zhuǎn)換動作不會修改原始數(shù)組耙替,而是產(chǎn)生一個全新的數(shù)組。

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
//對每個偶數(shù)元素翻倍镶殷,并丟棄奇數(shù)元素

一種等價方法

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

高效數(shù)組操作

//給定一個整數(shù)的數(shù)組緩沖,移除第一個負數(shù)之外的所有負數(shù)比吭。
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 }}}
//從數(shù)組緩沖中移除元素并不高效,把非負數(shù)值拷貝到前端比較好
var first = true
val indexes = 
for(i<-0 until a.length if first || a(i) >= 0)
    yield{
    if (a(i) < 0) first = false;//遇到第一個負數(shù)時置first = false,以后再遇到負數(shù)跋选,根據(jù) first||a(i)>=0 就直接跳過了
    i //i是下標
    }
for (j <- 0 until indexes.length) a(j) = a(indexes(j))
    a.trimEnd(a.length - indexes.length)

這里的關鍵點是音比,拿到所有下標好過逐個處理,一次就能處理完震鹉。

數(shù)組轉(zhuǎn)成映射(array轉(zhuǎn)Map)

假設一個場景磕仅,一個array中全是字符串玩裙,我們需要拿出最長的那個字符串,那么我們可以把這個array轉(zhuǎn)成Map,
映射表中為(str -> str.length)這種形式。
那么我們可以先用case轉(zhuǎn)化array為元祖篮绿,再用toMap轉(zhuǎn)化成映射。

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有內(nèi)建的函數(shù)來處理這些任務

Array(1,7,2, 9).sum // 19,對ArrayBuffer同樣適用

要使用sum方法怎诫,元素類型必須是數(shù)值類型:要么是整型尚镰,要么是浮點數(shù)或者Biglnteger/BigDecimal哆料。
同理,min和max輸出數(shù)組或數(shù)組緩沖中最小和最大的元素歹啼。

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

sorted方法將數(shù)組或數(shù)組緩沖排序并返回經(jīng)過排序的數(shù)組或數(shù)組緩沖,這個過程并不會修改原始版本:

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)

可以直接對一個數(shù)組排序,但不能對數(shù)組緩沖排序:

val a=Array(1,7,2,9)
scala.util.Sorting.quickSortIa(a) // a現(xiàn)在是Array(1,2,7,9)

顯示數(shù)組內(nèi)容
最后帐我,如果你想要顯示數(shù)組或數(shù)組緩沖的內(nèi)容蟀悦,可以用mkString方法,它允許你指定元素之間的分隔符季俩。該方法的另一個重載版本可以讓你指定前綴和后綴。例如:

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

和toString相比:
a.toString // " [I@85b8d",這里被調(diào)用的是Java的毫無意義的toString方法
b.toString // "ArrayBuffer(l,7,2, 9)"遇汞,toString方法報告了類型轨淌,便于調(diào)試

7.多維數(shù)組

多維數(shù)組是通過數(shù)組的數(shù)組來實現(xiàn)的狰域。舉例來說小压,Double的二維數(shù)組類型為:
Array[Array[Double]]
要構造這樣一個數(shù)組憋他,可以用ofDim方法:

val matrix=Array.ofDim[Double](3,4) //三行,四列要訪問其中的元素闯捎,使用兩對圓括號:
matrix (row) (column) =42

你可以創(chuàng)建不規(guī)則的數(shù)組祭犯,每一行的長度各不相同:

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

8.轉(zhuǎn)化

scala中的容器大部分可以使用toList檩禾,toSet灌灾,toArray炉奴,toMap等相互轉(zhuǎn)換
如果要轉(zhuǎn)化成java容器,例如scala List轉(zhuǎn)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會自動推導童漩,其值不能被改變脚线。你可以通過 -> 操作符來創(chuàng)建對偶。你也可以通過Map(("a", 1), ("b", 2))來創(chuàng)建對偶。

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")莹菱,調(diào)用返回字符串t。在Scala中吱瘩,映射.get(鍵)這樣的調(diào)用返回一個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.更新/新增一個鍵/值對,做法是在=號的左側(cè)使用()

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"被更新驾霜。在不變映射中案训,老的和新的映射共享大部分數(shù)據(jù)結構。
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)

注:不變映射中强霎,老的和新的映射共享大部分數(shù)據(jù)結構。

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) ...伐弹,如果你想反轉(zhuǎn)一個映射拉馋,則可使用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是一個數(shù)組绰精,里面是字符串,字符串格式前面是用戶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中的元素轉(zhuǎn)成映射
      val m = s.toString.split(",").map(x => {
        (x.split(":")(0).toString, x.split(":")(1).toInt)
      }).toMap
//把元素轉(zhuǎn)換的多個映射合并
//getOrElse如果沒有召回id就設為1硫椰,相乘沒有變化。
      res = res ++ m.map(t => t._1 -> (t._2 * res.getOrElse(t._1, 1)))
    }

7 可變Map和不可變Map相互轉(zhuǎn)換

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方法時產(chǎn)生了一個無法序列化的對象。
MapLike中的方法比如mapvalue/filterKeys之類的無法序列化捻艳,需要加
map(identity)
比如說udf中出現(xiàn)了filterKeys來剔除異常值驾窟,到這一步udf直接返回result_map,數(shù)據(jù)是可以出來的认轨,但是如果下面再對result_map是用map等需要分發(fā)的操作绅络,就會報錯,這是spark的一個bug嘁字。
在result_map后面加上.map(identity)恩急,就正常了。
網(wǎng)上也有說加上.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) //返回集合中數(shù)字元素的積;注意得是num型;
    println(combine_map.size)  //返回map的大小;
    println(combine_map.toArray) //集合轉(zhuǎn)數(shù)組;
    println(combine_map.toBuffer) //返回緩沖區(qū),包含了Map的所有元素;
    println(combine_map.toList) //返回List,包含了Map的所有元素;
    combine_map.get("test_101").getOrElse("不存在") //根據(jù)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=>{  //計算滿足指定條件的集合元素數(shù)量;
      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=>{   //循環(huán)map里的所有元素;
      println(x +"------------")
    })
 
  }
}

元組

映射是鍵/值對偶的集合。對偶是元組(tuple)的最簡單形態(tài)--元組是不同類型值的聚集遂唧。元組的值是通過將單個的值包含在圓括號中構成的盖彭。如召边,(1, 2.66, "lm")是一個元組類型為Tuple3[Int, Double, java.lang.String]的三元數(shù)組隧熙,元組類型也可寫為(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

注:你可以使用變量._下標 獲取值症昏,也可用變量 _下標獲取值。十分注意的是掘宪,和數(shù)組或字符串中的位置不同魏滚,元組的各組元從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的值不會被返回释移。元組可用于函數(shù)需要返回不止一個值的情況玩讳。

拉鏈操作

拉鏈操作锋边,即把多個值綁定在一起豆巨,以便他們能夠被一起處理往扔,這可以使用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方法將對偶轉(zhuǎn)換成映射蝗罗,即arr1.zip(arr2).toMap串塑。

在開發(fā)過程中桩匪,通常使用元組的場景比較單一傻昙,一般就是整合成(key,value)這樣配合reducebykey,swap之類的方法使用妆档,比如最簡單的單詞計數(shù)再排序过吻。

rdd.flatMap(line => line.split(" "))
.map(word => (word, 1)) //使用map把rdd中元素改成元祖再計數(shù)
.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

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乳绕,一起剝皮案震驚了整個濱河市洋措,隨后出現(xiàn)的幾起案子菠发,更是在濱河造成了極大的恐慌滓鸠,老刑警劉巖糜俗,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楔敌,居然都是意外死亡卵凑,警方通過查閱死者的電腦和手機胜臊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來织盼,“玉大人,你說我怎么就攤上這事危虱“u危” “怎么了弥雹?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵剪勿,是天一觀的道長厕吉。 經(jīng)常有香客問我头朱,道長项钮,這世上最難降的妖魔是什么欺殿? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任程拭,我火速辦了婚禮棍潘,結果婚禮上亦歉,老公的妹妹穿的比我還像新娘肴楷。我一直安慰自己,他們只是感情好砂客,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布媚创。 她就那樣靜靜地躺著彤恶,像睡著了一般声离。 火紅的嫁衣襯著肌膚如雪抵恋。 梳的紋絲不亂的頭發(fā)上弧关,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天世囊,我揣著相機與錄音株憾,去河邊找鬼。 笑死墙歪,一個胖子當著我的面吹牛虹菲,可吹牛的內(nèi)容都是我干的毕源。 我是一名探鬼主播霎褐,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歌粥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤枣购,失蹤者是張志新(化名)和其女友劉穎棉圈,沒想到半個月后眷蜓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吁系,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡汽纤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年肴掷,在試婚紗的時候發(fā)現(xiàn)自己被綠了呆瞻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痴脾。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡明郭,死狀恐怖薯定,靈堂內(nèi)的尸體忽然破棺而出话侄,到底是詐尸還是另有隱情吞杭,我是刑警寧澤芽狗,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布童擎,位于F島的核電站顾复,受9級特大地震影響芯砸,放射性物質(zhì)發(fā)生泄漏假丧。R本人自食惡果不足惜破喻,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一婴噩、第九天 我趴在偏房一處隱蔽的房頂上張望几莽。 院中可真熱鬧章蚣,春花似錦纤垂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琐谤。三九已至笑跛,卻和暖如春飞蹂,著一層夾襖步出監(jiān)牢的瞬間陈哑,已是汗流浹背惊窖。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留毁欣,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓岳掐,卻偏偏與公主長得像凭疮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子串述,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Scala與Java的關系 Scala與Java的關系是非常緊密的V唇狻! 因為Scala是基于Java虛擬機纲酗,也就是...
    燈火gg閱讀 3,440評論 1 24
  • 數(shù)組是一種可變的衰腌、可索引的數(shù)據(jù)集合。在Scala中用Array[T]的形式來表示Java中的數(shù)組形式 T[]觅赊。 v...
    時待吾閱讀 953評論 0 0
  • 少年壯志不言愁勸君惜取少年時 定長數(shù)組: Scala使用Array表示長度不變的數(shù)組scala> val nums...
    xhades閱讀 640評論 0 0
  • 可變和不可變集合 Scala中的集合可分為可變集合和不可變集合⌒苎剩可變集合可以當場被更新,不可變集合本身是不可變的。...
    liqing151閱讀 211評論 0 0
  • 原標題關于登記房產(chǎn)協(xié)助執(zhí)行的分析 房屋登記部門在實踐工作中經(jīng)常會需要配合法院辦理各種登記瞄崇,比如協(xié)助查封腮郊,協(xié)助執(zhí)行。...
    小好閱讀 531評論 1 2