Scala基础之集合常用方法

摘要:
ScalaBuilder引申:scalaBuilder设计模式场景1)当对象具有大量可选参数时。mapmap源码//第一个参数,传入一个函数,第二个参数为隐式参数,返回值和集合的类型一致都是Bdefmap[B,That]:That={//方法内部定义builder方法defbuilder={//extractedtokeepmethodsizeunder35bytes,sothatitcanbeJIT-inlined//调用repr方法valb=bfb.sizeHintb}//将上述builder方法的返回值赋值给bvalb=builderforb+=f//调用result方法,返回一个集合b.result} map总结1)map方法将某个函数应用到集合中的每个元素,并产生一个新集合。

Scala Builder

引申:scala Builder设计模式
场景
	1)当对象具有大量可选参数时。
	2)当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
	3)当构造过程必须允许被构造的对象有不同的表示时。

map

  • map源码
//第一个参数,传入一个函数,第二个参数为隐式参数,返回值和集合的类型一致都是B
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
//方法内部定义builder方法
    def builder = { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
    //调用repr方法
      val b = bf(repr)
      b.sizeHint(this)
      b
    }
    //将上述builder方法的返回值赋值给b
    val b = builder
    for (x <- this) b += f(x)
   //调用result方法,返回一个集合
    b.result
  } 
  • map总结
1)map方法将某个函数应用到集合中的每个元素,并产生一个新集合。
2)新产生集合的个数等于原集合的个数,个数大于原元素就会形成集合嵌套
3)元素(eg:String)应用到map方法传递的函数(eg elem=>elem.split(""))后产生的元素大于原元素,此时生成一个集合,最后形成一个集合嵌套
4)进行map的对象是只含一层的集合  

flatten

  • 总结
1)使用没用参数;
2)String最终会被扁平化到字符
3)返回的是集合
4)进行flatten的对象是可以嵌套的的集合

flatmap

  • 总结
1)输入什么集合,返回什么集合
2)flatmap方法传递的函数的参数是字符串
3)flatMap返回的个数则是不同与原集合个数
4)flatMap = map + flatten 即先对集合中的每个元素进行map,再对map后的每个元素(map后的每个元素必须还是集合)中的每个元素进行flatten
5)进行map的对象可以是只含一层的集合,但进行flatten操作的对象必需是至少含两层的集合 

filter : filter方法可以对集合中的每一条数据进行筛选过滤

  • 总结
1)输入什么类型集合,返回什么类型集合
2)满足条件(true)的数据保留,不满足条件(false)的数据丢弃 

groupby

  • 源码
groupby
def groupBy[K](f: A => K): immutable .Map [K,, Repr] = {
//创建一个可变map对象m->【k:K v:mutable.Bulder[A,Repr]】
//Bulder 元素为A,构建类型为Repr,它可以通过+=来向构造器中添加元素,通过result返回得到一个任意类型的集合

  val m: mutable.Map[K, mutable.Builder[A, Repr]] = mutable.Map.empty[K, Builder[Aj Repr]] 

//遍历集合,向m中添加元素,key为传过来的集合中的元素通过函数f()计算返回的结果,
//如果该key是在m中没有,则创建一个元素类型为A,构建类型为Repr的Builder对象放入value中,
//并让bldr指向该Builder对象,向bldr中添加元素elem(事实上是向m的value中添加elem)
/*

举例: 第一次f()计算结果是1,elem是"a",由于是第一次,则创建新的Builder给V,
此时m = (1 -> (“a”)),第二次f()计算结果还是1,elem是"b",
此时m=(1 ->(“a”,“b”)),第三次f()计算结果变成2了,elem是"c",
由于key->2第一次出现,则创建新的Builder,此时m=(1 ->(“a”,“b”),2 -> (“c”))

*/
for (elem <- this) {
    val key: K = f(elem)
    val bldr: mutable.Builder[A, Repr] = m.getOrElseUpdate(key, newBuilder) bldr += elem
  }
//创建一个构造器b,元素类型是Tupple2(K,Repr),构建类型是Map(K,Repr),遍历m,
//向b中添加k和v,将m的数据导入到构造器b中 调用result输出集合
  val b: mutable.Builder[(K, Repr), Map[K, Repr]] = immutable.Map.newBuilder[K,, Repr] 
for ((k, v) <- m)
    b += ((k, v.result))
  b.result 
  • 总结
1) groupBy传入的参数f(A)=>K,  A为调用函数的集合元素类型,K为输出map的key。
2) 输出map的value类型为调用函数的集合的类型  

sortby

  • 源码
//sortBy最后也是调用的sorted方法,隐式参数Ordering作用混入了Java的Comparator接口
//提供一个外部比较器

 def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)
//sorted源码
 def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
    val len = this.length
    val arr = new ArraySeq[A](len)
    var i = 0
    for (x <- this.seq) {
      arr(i) = x
      i += 1
    }
//sorted方法真正排序的逻辑是调用的java.util.Arrays.sort
//java中的sort用快速排序和优化的归并排序
//快速排序主要是对那些基本类型数据(int,short,long等)排序, 而归并排序用于对Object类型进行排序。
    java.util.Arrays.sort(arr.array, ord.asInstanceOf[Ordering[Object]])
    val b = newBuilder
    b.sizeHint(len)
    for (x <- arr) b += x
    b.result
  }  
  • 总结
java sort总结:
1)首先先判断需要排序的数据量是否大于60。
2)小于60:使用插入排序,插入排序是稳定的
3)大于60的数据量会根据数据类型选择排序方式:
    基本类型:使用快速排序。因为基本类型。1、2都是指向同一个常量池不需要考虑稳定性。
    Object类型:使用归并排序。因为归并排序具有稳定性。
4)注意:不管是快速排序还是归并排序。在二分的时候小于60的数据量依旧会使用插入排序

scala sort总结:
1)升序默认
2)"Hello Scala" compare "Hello React" 第一个单词首字母相同,比较第二个单词首字母
3)  Ordering.Int.reverse;隐式参数Ordering来做倒序排序 

mapVaules

  • 总结
1)处理什么集合,返回什么集合
Let's say we have a Map[A,B]. For clarification: I'm always referring to an immutable Map.
mapValues takes a function B => C, where C is the new type for the values 

partition

  • 源码
源码:
//箭头函数作为参数返回boolean,partition返回一个元组
  def partition(p: A => Boolean): (Repr, Repr) = {
// l,r是创建出来的2个集合对象
    val l, r = newBuilder
    for (x <- this) (if (p(x)) l else r) += x
//什么集合类型调用partition就返回什么类型的嵌套元组 eg (List(),List())
    (l.result, r.result)
  } 

sliding(滑动窗口,滚动窗口)

  • 总结
滑动窗口数据会造成重复
运用场景: 每隔30分钟统计前1个小时的数据 

zip

  • 总结
1)list1.zip(list2) 返回 list((),(),()) ;返回的集合类型嵌套元组
2)zipWithIndex,元素和索引映射

fold

  • 总结
fold方法传递2个部分的参数, 第一个部分表示集合之外的数据, 第二个部分的参数表示数据进行的逻辑处理
foldLeft 实例可以操作2个map,让key相同的value相加

补充命令

补充命令
intersect
union
diff
sliding
zip
reduce(相邻)
fold(折叠)
foldLeft
par
sortby
sortwith(自定义排序)
collect(偏函数) list.collect{
            case i : Int => i + 1
        } 

补充实例foldLeft

val list1 = List(1,2,3,4)
val map1 = mutable.Map(
      ("a", 1), ("b", 2), ("c", 3)
 )
val map2 = mutable.Map(
    ("a", 4), ("d", 5), ("c", 6)
)
val map3 = map2.foldLeft(map1)(
     (map, kv) => {
         val key = kv._1
          val cnt = kv._2
          val oldCnt = map.getOrElse(key, 0)
          map.update(key, oldCnt + cnt)
          map
      }
)

免责声明:文章转载自《Scala基础之集合常用方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇屏蔽文本框的粘贴操作(即,不允许从其他地方复制东西直接粘贴到该文本框中)Springboot基础核心下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

SpringBoot项目中@Async方法没有执行的问题分析

现象:1.明显的现象:在日志文件中找不到方法中的日志输出,并且没有错误报告(即,未执行@Async标记的方法,也没有错误报告)。2.分析现象:日志中某段时间后没有任务xxx线程的日志原因:@Async异步方法默认使用Spring创建ThreadPoolTaskExecutor(参考TaskExecutionAutoConfiguration),其中默认核心线...

微信扫码网页登录,redirect_uri参数错误解决方法

对于微信开放平台[管理中心/应用程序详细信息]中设置的[开发信息][授权回调域],只需填写域名,无需https://,也无需特定页面。您不需要填写完整的请求路径,如图所示:https://open.weixin.qq.com/connect/qrconnect?appid=您的APPID&direct_Uri=回调和响应的特定地址_type=code...

Android开发实战——记账本(4)

父母亲mCostBeanList.remove(位置);builder.setNegativeButton(“取消”;builder.create().show();returntrue;}returnsuper.onOptionsItemSelected(项);...

Qt使用镜像源快速安装与更新

如果我们选择在线安装模式,那就更麻烦了,因为下载速度一般不慢。事实上,在中国,Qt图片来源很多,但很少有人使用。原因是Qt图像源做得不好。如果我们导入它,它将自动链接到官方图像源。因为它已经从官方来源同步,没有更改,所以我们无法逐个添加补丁,这太麻烦了。好吧,让我停止胡说八道。让我告诉你如何使用国产Qt图像源。...

IDEA的设置打不开,点了没反应解决办法

把它去掉用回英文d就可以了。...

PowerQuery清理非文件名字符(清除指定列表中的所有字符)

在左侧导航窗格的空白区域右击,依次找到空白查询项接下来的思路是:遍历列表SearchList中的所有项,依次清理Data表中所有想要处理的列。第三个参数是一个函数:它告诉List.Accumulate函数,在每一次使用SearchList中某一项操作Data表时,其操作的方式是如何的。...