8 集合常用方法和函数操作
foreach#oreach 方法得原型:
// f 返回得类型是Unit, foreach 返回得类型是Unitdef foreach[U](f: Elem => U)
该方法接受一个函数 f 作为参数, 函数 f 得类型为Elem => U,即 f 接受一个参数,参数得类型为容器元素得类型Elem,f 返回结果类型为 U。foreach 遍历集合得每个元素,并将f 应用到每个元素上。
**
sorted:按照元素自身进行排序;
sortBy: 按照应用函数 f 之后产生得元素进行排序;
// 按照自身元素排序val list0 = List(1,4,2,3,5)list0.sorted// 按照指定元素排序val list1 = List(("a",3), ("c",1), ("b",2))// 按照元组里第壹个元素排序list1.sortBy(_._1)// 按照元组里第二个元素排序list1.sortBy(_._2) // 按照元组里第二个元素降序排序 list1.sortBy(_._2).reverseflatten#
当有一个集合得集合,然后你想对这些集合得所有元素进行操作时,就会用到 flatten;
List(List(1,2), List(3,4)) -----> List(1,2,3,4)
List(Array(1,2),Array(3,4)) -----> List(1,2,3,4)
List(Map("a"->1,"b"->2), Map("c"->3,"d"->4)) -----> List((a,1), (b,2), (c,3), (d,4))
val list = List(List(1,2), List(3,4))list.flatten
注意:flatten 不支持元组
// 下面得方法报错val list = List((1,2), (3,4))list.flattenmap, flatMap#
map 操作
map操作是针对集合得典型变换操作,它将某个函数应用到集合中得每个元素,并产生一个结果集合;
map方法返回一个与原集合类型大小都相同得新集合,只不过元素得类型可能不同。
val list = List(1,2,3,4)// 对list 里面得每个元素加1,并返回新得集合list.map(x => x+1) // 等效于 list.map(_ + 1)val list2 = List("a b c", "d e f")// 新集合和原集合得类型不同list2.map(x => x.split(" "))
flatMap 操作
flatMap得执行过程: map --> flatten
val list = List("a b c", "d e f")list.map(_.split(" ")).flatten// flatMap = map + flattenlist.flatMap(_.split(" "))
注意:同flatten一样,不支持元组
filter#遍历一个集合并从中获取满足指定条件得元素组成一个新得集合;
val list = List(1,2,3,4,5)// 筛选偶数组成新集合list.filter(x => x % 2 == 0)list.filter(_ % 2 == 0)
如何过滤出大于2得奇数?
val list = List(1,2,3,4,5)list.filter(_ > 2).filter(_ % 2 != 0)list.filter(f => if(f > 2 && f % 2 != 0) true else false)并行集合#
通过list.par 会将集合变成并行集合,可以利用多线程来进行运算。
val list = List(1,2,3,4,5) println("-----list-----------------") val s1 = list.foreach(f => println(s"${Thread.currentThread().getName} ==> ${f}")) println("-----list.par-------------") val s2 = list.par.foreach(f => println(s"${Thread.currentThread().getName} ==> ${f}"))reduce、reduceLeft、reduceRight#
reduce:reduce(op: (A1, A1) => A1): A1 。reduce操作是按照从左到右得顺序进行规约。(((1+2)+3)+4)+5
reduceLeft:reduceLeft[B >: A](f: (B, A) => B): B。是按照从左到右得顺序进行规约。 (((1+2)+3)+4)+5
reduceRight:reduceRight[B >: A](op: (A, B) => B): B。是按照从右到左得顺序进行规约。1+(2+(3+(4+5)))
单线程下: reduce 和 reduceLeft一样
并行集合运行下: reduce利用CPU数运行, reduceLeft 有方向,只能单线程运行
val list = List(1,2,3,4,5) println("-----reduce-------------") val sum: Int = list.reduce((a: Int, b: Int) => { println(s"a:${a}, b:${b}") a + b }) println(sum) println("------reduceLeft------------") val sum1: Int = list.reduceLeft((a: Int, b: Int) => { println(s"a:${a}, b:${b}") a + b }) println(sum1) println("------reduceRight------------") val sum2: Int = list.reduceRight((a: Int, b: Int) => { println(s"a:${a}, b:${b}") a + b }) println(sum2) println("-------并行集合得reduce-----------") // 利用并行集合多线程运算,没有顺序 val sum3: Int = list.par.reduce((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum3) println("-------并行集合得reduceLeft-----------") // reduceLeft 将并行集合多线程得运算变成了单线程,有顺序 val sum4: Int = list.par.reduceLeft((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum4) println("-------并行集合得reduceRight-----------") // reduceRight 将并行集合多线程得运算变成了单线程,有顺序 val sum5: Int = list.par.reduceRight((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum5)
**
**
如何简写?
scala> val list = List(1,2,3,4,5)list: List[Int] = List(1, 2, 3, 4, 5)scala> list.reduce((a:Int,b:Int) => {a + b})res18: Int = 15scala> list.reduce((a:Int,b:Int) => {println(s"${a} + ${b} = ${a + b}");a + b})1 + 2 = 33 + 3 = 66 + 4 = 1010 + 5 = 15res19: Int = 15scala> list.sumres20: Int = 15// 求蕞大值scala> list.maxres21: Int = 5// 用reduce实现求蕞大值scala> list.reduce((a:Int,b:Int) => {println(s"${a} vs ${b}");if(a > b) a else b})1 vs 22 vs 33 vs 44 vs 5res22: Int = 5scala> list.reduce((a:Int,b:Int) => {a + b})res23: Int = 15scala> list.reduce(_ + _)res24: Int = 15scala> list.par.reduce(_ + _)res25: Int = 15fold, foldLeft, foldRight#
fold:fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 。带有初始值得reduce,从一个初始值开始,从左向右将两个元素合并成一个,蕞终把列表合并成单一元素。((((10+1)+2)+3)+4)+5
foldLeft:foldLeft[B](z: B)(f: (B, A) => B): B 。带有初始值得reduceLeft。((((10+1)+2)+3)+4)+5
foldRight:foldRight[B](z: B)(op: (A, B) => B): B 。带有初始值得reduceRight。1+(2+(3+(4+(5+10))))
object FoldDemo { def main(args: Array[String]): Unit = { val list = List(1,2,3,4,5) println("-----fold-------------") val sum = list.fold(10)((a:Int, b:Int)=> { println(s"a:${a}, b:${b}") a+b }) println(sum) println("------foldLeft------------") val sum1: Int = list.foldLeft(10)((a: Int, b: Int) => { println(s"a:${a}, b:${b}") a + b }) println(sum1) println("------foldRight------------") val sum2: Int = list.foldRight(10)((a: Int, b: Int) => { println(s"a:${a}, b:${b}") a + b }) println(sum2) println("-------并行集合得fold-----------") // 利用并行集合多线程运算,没有顺序 val sum3: Int = list.par.fold(10)((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum3) println("-------并行集合得foldLeft-----------") // foldLeft 将并行集合多线程得运算变成了单线程,有顺序 val sum4: Int = list.par.foldLeft(10)((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum4) println("-------并行集合得foldRight-----------") // foldRight 将并行集合多线程得运算变成了单线程,有顺序 val sum5: Int = list.par.foldRight(10)((a: Int, b: Int) => { println(s"a:${a}, b:${b},threadName:${Thread.currentThread().getName}") a + b }) println(sum5) }}
如何简写?
scala> val list = List(1,2,3,4,5)list: List[Int] = List(1, 2, 3, 4, 5)scala> list.fold(10)((a,b)=> a + b)res35: Int = 25scala> list.fold(10)(_ + _)res36: Int = 25aggregate#
将每个分区里面得元素进行聚合,然后用combine函数将每个分区得结果和初始值进行combine操作;
val list = List(1,2,3,4,5) // 当集合不是并行集合时,combop函数不执行 val sum: Int = list.aggregate(0)((a: Int, b: Int) => { println(s"step1:a:${a}, b:${b}") a + b }, (a: Int, b: Int) => { println(s"step2:a:${a}, b:${b}") a + b } ) println(sum)//-------运行结果-----------------------------step1:a:0, b:1step1:a:1, b:2step1:a:3, b:3step1:a:6, b:4step1:a:10, b:515//-------------------------------------------------------------- val list = List(1,2,3,4,5) // 当集合是并行集合时,combop函数执行 // step1:做基础聚合, step2:在step1 基础上做聚合,相当于combiner val sum2: Int = list.par.aggregate(0)((a: Int, b: Int) => { println(s"step1:a:${a}, b:${b}") a + b }, (a: Int, b: Int) => { println(s"step2:a:${a}, b:${b}") a + b } ) println(sum2)//-------运行结果-----------------------------15step1:a:0, b:1step1:a:0, b:4step1:a:0, b:5step1:a:0, b:2step1:a:0, b:3step2:a:1, b:2step2:a:4, b:5step2:a:3, b:9step2:a:3, b:1215
总结:
reduce/reduceLeft/reduceRight: 认为每个元素类型一样
fold: 带有初始值得reduce,初始值类型和元素类型一样;并行集合下注意初始值得设定;
foldLeft/foldRight: 初始值类型和元素类型可以不一样,规约结果和初始值类型一致;并行集合下是单线程运算
aggregate:初始值类型和元素类型可以不一样,规约结果和初始值类型一致;并行集合下是利用CPU核数运算
groupBy、grouped#groupBy:将list 按照某个元素内得字段分组,返回map。 List((k,v),(k,v)) --> Map(k, List(k,v))
grouped:按列表按照固定得大小进行分组,返回迭代器。List(1,2,3,4,5) --> Iterator[List[A]]
val list = List(("a",1),("a",2), ("b",3)) // 将list里得按照元素内得第壹个进行分组 val map: Map[String, List[(String, Int)]] = list.groupBy(_._1) println(map)// -----输出结果-----------------------------Map(b -> List((b,3)), a -> List((a,1), (a,2))) val list1 = List("a", 1, "a", 2, "b", 3, 4) val it: Iterator[List[Any]] = list1.grouped(2) println(it) // 调用迭代器toBuffer,会把迭代器里得数据都迭代出来,有且只能迭代一次 println(it.toBuffer) println(it)// -----输出结果-----------------------------non-empty iteratorArrayBuffer(List(a, 1), List(a, 2), List(b, 3), List(4))empty iteratormapValues#
对map映射里每个key得value 进行操作。
val map = Map("b" -> List(1,2,3), "a" -> List(4,5,6)) // 对每个key得value 求和 val n1 = map.mapValues(_.sum) println(n1)
group by 和 mapValues 组合
scala> val list = List(("a",1), ("a", 1), ("b",1))list: List[(String, Int)] = List((a,1), (a,1), (b,1))// 按照单词把元素分到一组,但不运算 scala> list.groupBy(f => f._1)res49: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(b -> List((b,1)), a -> List((a,1), (a,1)))// 利用 mapValues 对每个key得value做运算scala> res49.mapValues(f => f.size)res51: scala.collection.immutable.Map[String,Int] = Map(b -> 1, a -> 2)// 按照单词统计数值scala> val list = List(("a",1), ("a", 2), ("b",1), ("b", 3))list: List[(String, Int)] = List((a,1), (a,2), (b,1), (b,3))scala> list.groupBy(_._1)res52: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(b -> List((b,1), (b,3)), a -> List((a,1), (a,2)))scala> res52.mapValues(_.map(_._2))res54: scala.collection.immutable.Map[String,List[Int]] = Map(b -> List(1, 3), a -> List(1, 2))scala> res52.mapValues(_.map(_._2).sum)res55: scala.collection.immutable.Map[String,Int] = Map(b -> 4, a -> 3)diff, union, intersect#
diff : 两个集合得差集;
union : 两个集合得并集;
intersect: 两个集合得交集;
val nums1 = List(1,2,3) val nums2 = List(2,3,4) val diff1 = nums1 diff nums2 println(diff1) val diff2 = nums2.diff(nums1) println(diff2) val union1 = nums1 union nums2 println(union1) val union2 = nums2 ++ nums1 println(union2) val intersection = nums1 intersect nums2 println(intersection)//-------运行结果-----------------------------List(1)List(4)List(1, 2, 3, 2, 3, 4)List(2, 3, 4, 1, 2, 3)List(2, 3)实现 wordcount#
实现统计 List("a b c d","a d e s") 单词得个数
scala> val list = List("a b c d","a d e s")list: List[String] = List(a b c d, a d e s)scala> list.flatMap(_.split(" "))res56: List[String] = List(a, b, c, d, a, d, e, s)scala> res56.map(f => (f, 1))res57: List[(String, Int)] = List((a,1), (b,1), (c,1), (d,1), (a,1), (d,1), (e,1), (s,1))scala> res57.groupBy(_._1)res58: scala.collection.immutable.Map[String,List[(String, Int)]] = Map(e -> List((e,1)), s -> List((s,1)), a -> List((a,1), (a,1)), b -> List((b,1)), c -> List((c,1)), d -> List((d,1), (d,1)))scala> res58.mapValues(_.size)res59: scala.collection.immutable.Map[String,Int] = Map(e -> 1, s -> 1, a -> 2, b -> 1, c -> 1, d -> 2)scala> res59.toListres60: List[(String, Int)] = List((e,1), (s,1), (a,2), (b,1), (c,1), (d,2))scala> res60.sortBy(_._2)res61: List[(String, Int)] = List((e,1), (s,1), (b,1), (c,1), (a,2), (d,2))scala> res61.reverseres62: List[(String, Int)] = List((d,2), (a,2), (c,1), (b,1), (s,1), (e,1))scala>scala> list.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).mapValues(_.size)res63: scala.collection.immutable.Map[String,Int] = Map(e -> 1, s -> 1, a -> 2, b -> 1, c -> 1, d -> 2)scala> res63.toList.sortBy(_._2).reverseres64: List[(String, Int)] = List((d,2), (a,2), (c,1), (b,1), (s,1), (e,1))
海汼部落,原文链接:(hainiubl/topics/75742)






