scala 可变list集合与内存清理的关系

每次调用函数时,如果给定的参数值集都没有memoized我想将结果放入 in-memory 。 一列用于存储结果,另一列用于存储参数值。如何最好地实现这个? 参数的类型不同,包括一些枚举。在 C# 中,通常使用 DataTable 。 Scala 中是否有等价的?
时间:17年05月11日原作者:
你可以使用一个 mutable.Map[TupleN[A1, A2,.. ., AN], R],或者如果内存是一个问题,一个 WeakHashMap [1] 。下面的定义( 构建在的记忆代码之上) 允许你轻松memoize函数有多个参数。 例如:import Memoize._
def reallySlowFn(i: Int, s: String): Int = {
Thread.sleep(3000)
i + s.length
val memoizedSlowFn = memoize(reallySlowFn _)
memoizedSlowFn(1,"abc")//returns 4 after about 3 seconds
memoizedSlowFn(1,"abc")//returns 4 almost instantly定义:/**
* A memoized unary function.
* @param f A unary function to memoize
* @param [T] the argument type
* @param [R] the return type
class Memoize1[-T, +R](f: T =& R) extends (T =& R) {
import scala.collection.mutable
//map that stores (argument, result) pairs
private[this] val vals = mutable.Map.empty[T, R]
//Given an argument x,
//If vals contains x return vals(x).
//Otherwise, update vals so that vals(x) == f(x) and return f(x).
def apply(x: T): R = vals getOrElseUpdate (x, f(x))
object Memoize {
* Memoize a unary (single-argument) function.
* @param f the unary function to memoize
def memoize[T, R](f: T =& R): (T =& R) = new Memoize1(f)
* Memoize a binary (two-argument) function.
* @param f the binary function to memoize
* This works by turning a function that takes two arguments of type
* T1 and T2 into a function that takes a single argument of type
* (T1, T2), memoizing that"tupled" function, then"untupling" the
* memoized function.
def memoize[T1, T2, R](f: (T1, T2) =& R): ((T1, T2) =& R) =
Function.untupled(memoize(f.tupled))
* Memoize a ternary (three-argument) function.
* @param f the ternary function to memoize
def memoize[T1, T2, T3, R](f: (T1, T2, T3) =& R): ((T1, T2, T3) =& R) =
Function.untupled(memoize(f.tupled))
//... more memoize methods for higher-arity functions.. .
* Fixed-point combinator (for memoizing recursive functions).
def Y[T, R](f: (T =& R) =& T =& R): (T =& R) = {
lazy val yf: (T =& R) = memoize(f(yf)(_))
}fixed-point组合器( Memoize.Y ) 使memoize函数成为可能:val fib: BigInt =& BigInt = {
def fibRec(f: BigInt =& BigInt)(n: BigInt): BigInt = {
if (n == 0) 1
else if (n == 1) 1
else (f(n-1) + f(n-2))
Memoize.Y(fibRec)
}[1] WeakHashMap作为缓存工作不正常。 参见
anovstrup建议的使用可变映射的版本与 C# 基本相同,因此易于使用。但是如果你想你也可以使用更多功能的风格。 它使用了不可变的映射,作为一种 accumalator 。 使元组( 示例中没有 Int ) 作为键工作在可变大小写中。def fib(n:Int) = fibM(n, Map(0-&1, 1-&1))._1
def fibM(n:Int, m:Map[Int,Int]):(Int,Map[Int,Int]) = m.get(n) match {
case Some(f) =& (f, m)
case None =& val (f_1,m1) = fibM(n-1,m)
val (f_2,m2) = fibM(n-2,m1)
val f = f_1+f_2
(f, m2 + (n -& f))
}当然这稍微有点复杂,但这是一个了解( 注意上面的代码是为了清晰,而不是为了速度)的有用技术。
作为这个主题的新手,我可以完全理解( 不过还是要感谢) 中的所有例子。 尊重,我将自己的解决方案中有人来这儿有一个相同的水平,同样的问题。 我认为我的代码对于那些仅仅拥有 的任何人都是透明的。def MyFunction(dt : DateTime, param : Int) : Double
val argsTuple = (dt, param)
if(Memo.contains(argsTuple)) Memo(argsTuple) else Memoize(dt, param, MyRawFunction(dt, param))
def MyRawFunction(dt : DateTime, param : Int) : Double
1.0//A heavy calculation/querying here
def Memoize(dt : DateTime, param : Int, result : Double) : Double
Memo += (dt, param) -& result
val Memo = new scala.collection.mutable.HashMap[(DateTime, Int), Double]完美的工作。如果我错过了一些东西,我将很欣赏。
当使用可变地图记忆,应当记住,这将导致一个典型的并发性问题, 比如 做时写尚未完成。 然而,thread-safe图谋的记忆表明这样做是没有价值的,如果不是没有。以下thread-safe代码创建一个 memoized fibonacci 函数,初始化一对线程( 命名自',并调用调用它的'通过到'd') 。 在( 在替换中) 中多次尝试代码,可以很容易地看到 f(2) set 被打印多次。 这意味着线程A 已经开始计算 f(2),但是线程B 完全不知道它并启动它自己的计算副本。 这样的无知是普遍的在构建阶段的缓存,因为没有看到子解决方案建立和所有线程将进入 else 条款。object ScalaMemoizationMultithread {
//do not use case class as there is a mutable member here
class Memo[-T, +R](f: T =& R) extends (T =& R) {
//don't even know what would happen if immutable.Map used in a multithreading context
private[this] val cache = new java.util.concurrent.ConcurrentHashMap[T, R]
def apply(x: T): R =
//no synchronized needed as there is no removal during memoization
if (cache containsKey x) {
Console.println(Thread.currentThread().getName() +": f(" + x +") get")
cache.get(x)
val res = f(x)
Console.println(Thread.currentThread().getName() +": f(" + x +") set")
cache.putIfAbsent(x, res)//atomic
object Memo {
def apply[T, R](f: T =& R): T =& R = new Memo(f)
def Y[T, R](F: (T =& R) =& T =& R): T =& R = {
lazy val yf: T =& R = Memo(F(yf)(_))
val fibonacci: Int =& BigInt = {
def fiboF(f: Int =& BigInt)(n: Int): BigInt = {
if (n &= 0) 1
else if (n == 1) 1
else f(n - 1) + f(n - 2)
Memo.Y(fiboF)
def main(args: Array[String]) = {
('a' to 'd').foreach(ch =&
new Thread(new Runnable() {
def run() {
import scala.util.Random
val rand = new Random
(1 to 2).foreach(_ =& {
Thread.currentThread().setName("Thread" + ch)
fibonacci(5)
除了landei的回答,我还想建议自底向上( non-memoization ) Scala 中这样进行DP的是可能的,并且它的核心是给使用 foldLeft ( s ) 。计算 斐波那契数列的示例 def fibo(n: Int) = (1 to n).foldLeft((0, 1)) {
(acc, i) =& (acc._2, acc._1 + acc._2)
}._1最长递增子序列的示例def longestIncrSubseq[T](xs: List[T])(implicit ord: Ordering[T]) = {
xs.foldLeft(List[(Int, List[T])]()) {
(memo, x) =&
if (memo.isEmpty) List((1, List(x)))
val resultIfEndsAtCurr = (memo, xs).zipped map {
(tp, y) =&
val len = tp._1
val seq = tp._2
if (ord.lteq(y, x)) {//current is greater than the previous end
(len + 1, x :: seq)//reversely recorded to avoid O(n)
(1, List(x))//start over
memo :+ resultIfEndsAtCurr.maxBy(_._1)
}.maxBy(_._1)._2.reverse
Copyright (C) 2011 HelpLib All rights reserved. &&Scala强大的集合数据操作代码示例 - 简书
Scala强大的集合数据操作代码示例
明确目标,掌握方法,慢下来,等待时间的流逝,知识浸润到身体
每天学习英语1小时
记录每天的所学所想
微信号:xy 跟凯哥一起学编程
在此特此声明:一下所有链接均来自互联网,在此记录下我的查阅学习历程,感谢各位原创作者的无私奉献 ! 技术一点一点积累,很多知识不是看一次就记住了,需要深入去理解,在实际开发中去进一步领会 再待我技术上一个层面时,也会把自己理解的技术点分享出来! 启动页相关 iOS启动时如何...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金相信有很多朋友...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金相信有很多朋友...
Android资料 http://services.gradle.org/distributions/
gardle下载地址 http://rj.baidu.com/soft/lists/13
01 上周末看了一个短视频,大意是现在人们的节奏越来越快,而导致这种现象的原因,是技术的进步与信息的畅通。于是视频鼓励我们不妨慢一点,适当的放下手机与信息的接收。 若不是自己在这一块有过切实的感受,看完这个视频,我可能又会矫情一下,“嗯,很有道理,我得再去体验体验慢生活。”...
在古城东门外有一小片人工种植的桃林,掩映在灌木丛中。每年春天桃花盛开的时候,总有许多女人相约去观赏桃花,我去年去过一次,今年又去了一次,发现男人很少去。看桃花似乎是女人的专利,我经常在朋友圈看到一些女性朋友晒出照片,她们手扶花枝,脸庞依偎,或特写,或全景,尽显妩媚。确实,女...
昨夜狂风,骤雨堂东。 待晨起,后庭无人。 行人乱处,更碎残红。 渐无人惜,无人问,无人从。 年年花事,花事难同。 恨人也,难顾芳容。 烟桥别后,愁对蟾宫。 又几回梦,几回泪,几回逢。
在赶来相见的路上, 我已开始想你, 等不及构建画面, 从气味开始思念; 不来自香水, 或者化妆品, 纯纯粹粹, 鼻腔中全是你的味道; 搓揉发尾, 会扬起淡淡清香, 吻在脸上, 热乎乎得呵气如兰; 还有, 只有夜幕降临以后, 依偎着才能闻到, 湿漉漉的浓郁芬芳; 彷佛蒙起双眼...
近日,AWE2018中国新零售领袖峰会在上海举行,参与者各抒己见,现场可谓百家争鸣。苏宁立足新服务,重点提及了“30365”服务升级项目,简言之,只要产品质量出现问题,30天包退,365天包换。此言一出,不少人提出质疑:苏宁能否扛得住用户退货?它的底气在哪呢? 一、春节消费...列表的初始化及对其首尾的访问:
scala& val colors = List("red", "blue", "green")
colors: List[String] = List(red, blue, green)
scala& colors.head
res15: String = red
scala& colors.tail
res16: List[String] = List(blue, green)
创建长度已知但内容未知的数组:
scala& val fiveInts = new Array[Int](5)
fiveInts: Array[Int] = Array(0, 0, 0, 0, 0)
根据已知元素初始化数组:
scala& val fiveToOne = Array(5, 4, 3, 2, 1)
fiveToOne: Array[Int] = Array(5, 4, 3, 2, 1)
访问和更新数组元素:
scala& fiveInts(0) = fiveToOne(4)
scala& fiveInts
res18: Array[Int] = Array(1, 0, 0, 0, 0)
ListBuffer是可变对象(包含在scala.collection.mutable包中),它可以更高效地通过添加元素的方式构建列表。ListBuffer能够支持常量时间的添加和前缀操作。元素的添加使用+=操作符,前缀使用+:操作符。完成之后,可以通过ListBuffer调用toList方法获得List。举例如下:
scala& val buf = new ListBuffer[Int]
buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer()
scala& buf += 1
res20: buf.type = ListBuffer(1)
scala& buf += 2
res21: buf.type = ListBuffer(1, 2)
scala& buf
res22: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2)
scala& 3 +: buf
res23: scala.collection.mutable.ListBuffer[Int] = ListBuffer(3, 1, 2)
scala& buf.toList
res24: List[Int] = List(1, 2)
ArrayBuffer与数组类似,只是额外还允许你在序列的开始或结束的地方添加和删除元素。所有的Array操作都被保留,只是由于实现中的包装层导致执行的稍微有些慢。
创建ArrayBuffer的时候,你必须指定它的类型参数,但可以不指定长度。ArrayBuffer可以自动调整分配的空间:
ArrayBuffer还能用+=操作添加元素:
scala& import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala& val buf = new ArrayBuffer[Int]()
buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala& buf += 12
res27: buf.type = ArrayBuffer(12)
scala& buf += 15
res29: buf.type = ArrayBuffer(12, 15)
所有数组能使用的方法数组缓存都能用。如可以获得ArrayBuffer的长度,或通过索引访问元素:
scala& buf.length
res30: Int = 2
scala& buf(0)
res31: Int = 12
队列Scala的集合库提供了可变和不可变的Queue。以下方法创建空的不可变队列:
scala& import scala.collection.immutable.Queue
import scala.collection.immutable.Queue
scala& val empty = Queue[Int]()
empty: scala.collection.immutable.Queue[Int] = Queue()
可以使用enqueue为不可变队列添加元素:
scala& val has1 = empty.enqueue(1)
has1: scala.collection.immutable.Queue[Int] = Queue(1)
如果要添加多个元素的话,可以把集合当作enqueue调用的参数:
scala& val has123 = has1.enqueue(List(2, 3))
has123: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3)
从队列的头部移除元素,可以使用dequeue:
scala& val (element, has23) = has123.dequeue
element: Int = 1
has23: scala.collection.immutable.Queue[Int] = Queue(2, 3)
对于不可变队列来说,dequeue方法将返回由队列头部元素和移除该元素之后的剩余队列组成的对偶(Tuple2)。可变队列的使用方式与不可变队列一样,只是代之以enqueue方法,可以使用+=及++=操作符添加元素。还有,对于可变队列来说,dequeue方法将只从队列移除头元素并返回。举例如下:
scala& import scala.collection.mutable.Queue
import scala.collection.mutable.Queue
scala& val queue = Queue[String]()
queue: scala.collection.mutable.Queue[String] = Queue()
scala& queue += "a"
res0: queue.type = Queue(a)
scala& queue ++= List("b", "c")
res1: queue.type = Queue(a, b, c)
scala& queue
res2: scala.collection.mutable.Queue[String] = Queue(a, b, c)
scala& queue.dequeue
res3: String = a
scala& queue
res4: scala.collection.mutable.Queue[String] = Queue(b, c)
Stack同样在Scala的集合库中有可变和不可变两个版本。元素的推入使用push,弹出使用pop,只获取栈顶的元素而不移除可以使用top。下面是使用可变栈的例子:
scala& import scala.collection.mutable.Stack
import scala.collection.mutable.Stack
scala& val stack = new Stack[Int]
stack: scala.collection.mutable.Stack[Int] = Stack()
scala& stack.push(1)
res5: stack.type = Stack(1)
scala& stack
res6: scala.collection.mutable.Stack[Int] = Stack(1)
scala& stack.push(2)
res7: stack.type = Stack(2, 1)
scala& stack
res8: scala.collection.mutable.Stack[Int] = Stack(2, 1)
scala& stack.top
res9: Int = 2
scala& stack
res10: scala.collection.mutable.Stack[Int] = Stack(2, 1)
scala& stack.pop
res11: Int = 2
scala& stack
res12: scala.collection.mutable.Stack[Int] = Stack(1)
字符串(经RichString隐式转换)
RichString也是应该知道的序列,它的类型是Seq[Char]。因为Predef包含了从String到RichString的隐式转换,所以你可以把任何字符串当作Seq[Char]。举例如下:
scala& def hasUpperCase(s:String) = s.exists(_.isUpper)
hasUpperCase: (s: String)Boolean
scala& hasUpperCase("Robert Frost")
res13: Boolean = true
scala& hasUpperCase("e e cummings")
res14: Boolean = false
阅读(...) 评论()Scala 在大数据处理方面有何优势? - 知乎822被浏览<strong class="NumberBoard-itemValue" title="5分享邀请回答scala-lang.org/news/roadmap-next)将要简化语法,推出Scala "Don Giovanni"项目的时候,在视频中说的很清楚:“Scala现在是为聪明人创造的,以后也是为聪明人服务的。”所以不同于Python让程序员用一种方法做所有事情,Scala提供一整套工具,让程序员自由选择,无论是mutable数据结构,immutable数据结构,并行(parallel)数据结构。然后在这些选择中,Scala再针对他们进行算法层面的特殊优化。Scala相信程序员的聪明才智,让程序员自行选择合适的结构,以针对变化万千的任务需求,这点是Scala做得极好的地方。再者,有人会说immutable数据结构占用内存,或者速度很慢。这是真的,但这不是Scala的错,而是这些结构就是这样定义的。可以看看这个视频: 这里讲的是Scala集合的运行速度,是一个来自Goldman Sachs的程序员讲他们为Java写的集合库(GSCollection)速度和内存消耗,但同时比较了gs-collection(),Java,和Scala库的速度。最后Scala的可变集合mutable原生库完爆Java,和gs-collection基本持平。Scala的第二个优势,相较于Java而言,则是相信程序员的优化能力。在Scala with Style讲话中(),马丁·奥德斯基说:“很多程序员会告诉我,他们一般会重构他们的Scala代码两三次,甚至三四次。”这听起来似乎非常的没有效率,但Scala就是这样的语言,每一次重构,代码的性能或者是可读性都会有极高的提升。之前就有人提到过,Scala新手和老手写出来的代码完全会呈现两种不同的风格,甚至新人根本不能读懂有经验的Scala程序员所写的代码,有人于是戏称:“太好了,这样的话我们部门的实习生就不能乱碰我写的代码啦!”但其实不仅风格不同,执行效率差距也一定是巨大的。Scala提供一整套工具,但是要明白什么时候用拿一种工具,哪些算法能够随意调用,哪些算法不能,这一定要依靠经验、研究和学习以及对源代码的理解才能得知。最简单的例子,Scala的foreach()方法是高度优化过了的(尤其针对Range结构和Vector结构),但是fold()就不一定了。或者当受到诱惑想用zipWithIndex()的时候,一定要明白这是两次循环,最好改用Vector(...).indices.foreach()的方法,或者用.view来推迟执行。像这样的地方还有很多。所以在这个层面上来讲,简直和C++非常的相似。从另外一个层面来讲,不仅仅是要理解语言层面的优化,Scala作为一个社区而言,是非常追求运行速度的。Ruby社区就完全不同了,Ruby曾经是推特的主要语言。推特的团队找到了Ruby团队,说,你们能不能让Ruby运行的快一点,我们有这个这个和这个建议。Ruby直接把这些建议拒绝了,因为它们会增加语言复杂度,让Ruby不能继续做一个“fun”(好玩)的语言。而Python直接就立志做一个“Simple”(简单)的语言了。于是推特只好将后台换做Scala和Java的结合。有一位在推特工作的知乎友人在我的一个回答下留言说推特换用Scala后,TypeSafe(Scala的母公司)还送去了一个蛋糕。为了追求速度,Scala社区是绝对不会管所谓的“简单”或者是“好玩”,怎样有效率就怎样弄。与其专注于JVM的改进,Scala社区大部分在编译器上下功夫,比如很著名的Miniboxing(),这是一个编译器增进器。Miniboxing做的是什么呢?只做一件事:防止auto-boxing和auto-unboxing。所有的泛型,尤其是原生类泛型(Primitive Types),诸如Int、Double等等,在进行各种操作的时候会自动取出和装回它们所属的类中去——这个我解释的不太好,但是可以看这里()。Miniboxing这样的插件可以让所有的原生类泛型再也不用自动装拆箱,从而将Scala的运行速度提升1.5倍到22倍()。当然这样的东西可不是白来的,这是马丁·奥德斯基的PhD博士学生做的一个研究项目,然后为OOPSLA写了一篇论文(),所以怪不得这玩意Scala可以有,但其他语言想要有都没有。另一个Scala的很大优势就是所谓的Macro——宏。宏本身作为元编程而言,其实和运行速度是没有什么太大关系的,反而,因为对反射(Reflect)的利用,可能会影响到速度。但Scala社区对宏的理解显然和最初的设计理念有偏差。因为Scala本身是没有传统意义的循环的(for-loop),所以很多时候循环必须利用while或者foreach。但是部分追求效率的Scala程序员们利用宏为Scala写了一个传统循环,叫做cfor,被收录在Spire()数学计算库中。cfor的写法如下:import spire.syntax.cfor._
// print numbers 1 through 10
cfor(0)(_ & 10, _ + 1) { i =&
println(i)
而这玩意运行效率如何呢? 文章中做了一次测评,将cfor和zip写的一个算法作比较——在公布结果之前,我想说的是,zip并不是一个高度优化的方法,所以本身就慢很多,cfor用了26.1毫秒运行,zip方法用了7.4 秒运行,这几乎是284倍的速度差距。通过这两点,Scala的一个优势就很明显了——多样化。当需要写简单的代码,像Python一样当脚本语言使用时,Scala提供大量的原生方法和数据结构,可以很轻松的写出比较复杂的操作。但当需要速度的时候,又可以通过重构来获取数十倍或者上百倍的速度提升。通过Miniboxing一类的编译器增强器,Scala在某些操作的速度是必定超过Java的。Scala的第二个优势就是——一帮勤劳勇敢的PhD博士生。二十一世纪的程序语言和二十世纪的程序语言已经不能比拟了。那个年代的普通人(甚至是学生)还能任意发明一下语言,稍微把编译器优化几次就能上得了厅堂(比如那一大堆Lisp方言),到了这个年代,编译技术已经达到了很复杂的程度(虚拟机技术也是如此),优化和语义理解,程序语言的定义与延展,再也不是随便任何人都能搞定的工作了。作为编程语言方面的教授,马丁·奥德斯基不断的将最前沿的学术界成果转移到Scala这个语言中,还让他的博士学生发展出新的,让语言运行得更快的方法,这些都是其他语言,尤其是Python、Ruby、甚至是Go都没有的优势。当然,说了这么多,总会有人说了,Scala如果像C++一样难,又追求速度的话,为什么不直接去学C++,原因很简单——现在有很多在JVM上面写成的软件啊!大家又不是Haskell程序员,压根不打算一切自己写呐。算是借花献佛,关注大数据欢迎加我微信 idacker143 条评论分享收藏感谢收起转自:http://blog.csdn.net/pzw_0612/article/details/
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That
需要传入一个偏函数,来保存符合其条件的值
val sample =1 to 10
//[]里面,第一个参数表示输入值,第二个参数是输出值
val isEven:PartialFunction[Int,String]={
case x if x%2== 0 =&x+" is even"
//case _ =&"this is not even"
val isOdd:PartialFunction[Int,String]={
case x if x%2!=0 =&x+" is odd"
//collect 里面要放一个partialFunction,作为组成集合的判断的条件
val evenNumbers = sample.collect(isEven)
//List(2,4,6,8,10)
map[B](f: (A) ? B): List[B]
定义一个变换,把该变换应用到列表的每个元素中,原列表不变,返回一个新的列表数据
Example1 平方变换
&val nums = List(1,2,3)
val square = (x: Int) =& x*x
val squareNums1 = nums.map(num =& num*num)
//List(1,4,9)
val squareNums2 = nums.map(math.pow(_,2))
//List(1,4,9)
val squareNums3 = nums.map(square)
//List(1,4,9)de&
Example2 保存文本数据中的某几列
&val text = List("Homeway,25,Male","XSDYM,23,Female")
val usersList = text.map(_.split(",")(0))
val usersWithAgeList = text.map(line =& {
val fields = line.split(",")
val user = fields(0)
val age = fields(1).toInt
(user,age)
2.flatMap, flatten
flatten: flatten[B]: List[B] 对列表的列表进行平坦化操作 flatMap: flatMap[B](f: (A) ? GenTraversableOnce[B]): List[B] map之后对结果进行flatten
定义一个变换f, 把f应用列表的每个元素中,每个f返回一个列表,最终把所有列表连结起来。
&val text = List("A,B,C","D,E,F")
val textMapped = text.map(_.split(",").toList) // List(List("A","B","C"),List("D","E","F"))
val textFlattened = textMapped.flatten
// List("A","B","C","D","E","F")
val textFlatMapped = text.flatMap(_.split(",").toList) // List("A","B","C","D","E","F")de&
reduce[A1 &: A](op: (A1, A1) ? A1): A1
定义一个变换f, f把两个列表的元素合成一个,遍历列表,最终把列表合并成单一元素
Example 列表求和
val nums = List(1,2,3)
val sum1 = nums.reduce((a,b) =& a+b)
val sum2 = nums.reduce(_+_)
val sum3 = nums.sum
4.reduceLeft,reduceRight
reduceLeft: reduceLeft[B &: A](f: (B, A) ? B): B
reduceRight: reduceRight[B &: A](op: (A, B) ? B): B
reduceLeft从列表的左边往右边应用reduce函数,reduceRight从列表的右边往左边应用reduce函数
val nums = List(2.0,2.0,3.0)
val resultLeftReduce = nums.reduceLeft(math.pow)
// = pow( pow(2.0,2.0) , 3.0) = 64.0
val resultRightReduce = nums.reduceRight(math.pow) // = pow(2.0, pow(2.0,3.0)) = 256.0de&
5.fold,foldLeft,foldRight
fold: fold[A1 &: A](z: A1)(op: (A1, A1) ? A1): A1&带有初始值的reduce,从一个初始值开始,从左向右将两个元素合并成一个,最终把列表合并成单一元素。
foldLeft: foldLeft[B](z: B)(f: (B, A) ? B): B 带有初始值的reduceLeft
foldRight: foldRight[B](z: B)(op: (A, B) ? B): B 带有初始值的reduceRight
val nums = List(2,3,4)
val sum = nums.fold(1)(_+_)
// = 1+2+3+4 = 9
val nums = List(2.0,3.0)
val result1 = nums.foldLeft(4.0)(math.pow) // = pow(pow(4.0,2.0),3.0) = 4096
val result2 = nums.foldRight(1.0)(math.pow) // = pow(1.0,pow(2.0,3.0)) = 8.0de&
6.sortBy,sortWith,sorted
sortBy: sortBy[B](f: (A) ? B)(implicit ord: math.Ordering[B]): List[A] 按照应用函数f之后产生的元素进行排序
sorted: sorted[B &: A](implicit ord: math.Ordering[B]): List[A] 按照元素自身进行排序
sortWith: sortWith(lt: (A, A) ? Boolean): List[A] 使用自定义的比较函数进行排序
&val nums = List(1,3,2,4)
val sorted = nums.sorted
//List(1,2,3,4)
val users = List(("HomeWay",25),("XSDYM",23))
val sortedByAge = users.sortBy{case(user,age) =& age}
//List(("XSDYM",23),("HomeWay",25))
val sortedWith = users.sortWith{case(user1,user2) =& user1._2 & user2._2} //List(("XSDYM",23),("HomeWay",25))de&
7.filter, filterNot
filter: filter(p: (A) ? Boolean): List[A]
filterNot: filterNot(p: (A) ? Boolean): List[A]
filter&保留列表中符合条件p的列表元素&, filterNot,保留列表中不符合条件p的列表元素
&val nums = List(1,2,3,4)
val odd = nums.filter( _ % 2 != 0) // List(1,3)
val even = nums.filterNot( _ % 2 != 0) // List(2,4)de&
count(p: (A) ? Boolean): Int
计算列表中所有满足条件p的元素的个数,等价于 filter(p).length
val nums = List(-1,-2,0,1,2) val plusCnt1 = nums.count( & 0) val plusCnt2 = nums.filter( & 0).length&9. diff, union, intersect
diff:diff(that: collection.Seq[A]): List[A] 保存列表中那些不在另外一个列表中的元素,即从集合中减去与另外一个集合的交集
union : union(that: collection.Seq[A]): List[A] 与另外一个列表进行连结
intersect: intersect(that: collection.Seq[A]): List[A] 与另外一个集合的交集
&val nums1 = List(1,2,3)
val nums2 = List(2,3,4)
val diff1 = nums1 diff nums2
// List(1)
val diff2 = nums2.diff(num1)
// List(4)
val union1 = nums1 union nums2
// List(1,2,3,2,3,4)
val union2 = nums2 ++ nums1
// List(2,3,4,1,2,3)
val intersection = nums1 intersect nums2
//List(2,3)de&
10.distinct
distinct: List[A] 保留列表中非重复的元素,相同的元素只会被保留一次
&val list = List("A","B","C","A","B") val distincted = list.distinct // List("A","B","C")de&
11.groupBy, grouped
groupBy : groupBy[K](f: (A) ? K): Map[K, List[A]] 将列表进行分组,分组的依据是应用f在元素上后产生的新元素&grouped: grouped(size: Int): Iterator[List[A]] 按列表按照固定的大小进行分组
&val data = List(("HomeWay","Male"),("XSDYM","Femail"),("Mr.Wang","Male"))
val group1 = data.groupBy(_._2) // = Map("Male" -& List(("HomeWay","Male"),("Mr.Wang","Male")),"Female" -& List(("XSDYM","Femail")))
val group2 = data.groupBy{case (name,sex) =& sex} // = Map("Male" -& List(("HomeWay","Male"),("Mr.Wang","Male")),"Female" -& List(("XSDYM","Femail")))
val fixSizeGroup = data.grouped(2).toList // = Map("Male" -& List(("HomeWay","Male"),("XSDYM","Femail")),"Female" -& List(("Mr.Wang","Male")))de&
scan[B &: A, That](z: B)(op: (B, B) ? B)(implicit cbf: CanBuildFrom[List[A], B, That]): That
由一个初始值开始,从左向右,进行积累的op操作,这个比较难解释,具体的看例子吧。
&val nums = List(1,2,3)
val result = nums.scan(10)(_+_)
// List(10,10+1,10+1+2,10+1+2+3) = List(10,11,12,13)de&
13.scanLeft,scanRight
scanLeft: scanLeft[B, That](z: B)(op: (B, A) ? B)(implicit bf: CanBuildFrom[List[A], B, That]): That
scanRight: scanRight[B, That](z: B)(op: (A, B) ? B)(implicit bf: CanBuildFrom[List[A], B, That]): That
scanLeft: 从左向右进行scan函数的操作,scanRight:从右向左进行scan函数的操作
&val nums = List(1.0,2.0,3.0)
val result = nums.scanLeft(2.0)(math.pow)
// List(2.0,pow(2.0,1.0), pow(pow(2.0,1.0),2.0),pow(pow(pow(2.0,1.0),2.0),3.0) = List(2.0,2.0,4.0,64.0)
val result = nums.scanRight(2.0)(math.pow)
// List(2.0,pow(3.0,2.0), pow(2.0,pow(3.0,2.0)), pow(1.0,pow(2.0,pow(3.0,2.0))) = List(1.0,512.0,9.0,2.0)de&
14.take,takeRight,takeWhile
take : takeRight(n: Int): List[A] 提取列表的前n个元素 takeRight: takeRight(n: Int): List[A] 提取列表的最后n个元素 takeWhile: takeWhile(p: (A) ? Boolean): List[A] 从左向右提取列表的元素,直到条件p不成立
&val nums = List(1,1,1,1,4,4,4,4)
val left = nums.take(4)
// List(1,1,1,1)
val right = nums.takeRight(4) // List(4,4,4,4)
val headNums = nums.takeWhile( _ == nums.head)
// List(1,1,1,1)de&
15.drop,dropRight,dropWhile
drop: drop(n: Int): List[A] 丢弃前n个元素,返回剩下的元素 dropRight: dropRight(n: Int): List[A] 丢弃最后n个元素,返回剩下的元素 dropWhile: dropWhile(p: (A) ? Boolean): List[A] 从左向右丢弃元素,直到条件p不成立
&val nums = List(1,1,1,1,4,4,4,4)
val left = nums.drop(4)
// List(4,4,4,4)
val right = nums.dropRight(4) // List(1,1,1,1)
val tailNums = nums.dropWhile( _ == nums.head)
// List(4,4,4,4)de&
16.span, splitAt, partition
span : span(p: (A) ? Boolean): (List[A], List[A]) 从左向右应用条件p进行判断,直到条件p不成立,此时将列表分为两个列表
splitAt: splitAt(n: Int): (List[A], List[A]) 将列表分为前n个,与,剩下的部分
partition: partition(p: (A) ? Boolean): (List[A], List[A]) 将列表分为两部分,第一部分为满足条件p的元素,第二部分为不满足条件p的元素
&val nums = List(1,1,1,2,3,2,1)
val (prefix,suffix) = nums.span( _ == 1) // prefix = List(1,1,1), suffix = List(2,3,2,1)
val (prefix,suffix) = nums.splitAt(3)
// prefix = List(1,1,1), suffix = List(2,3,2,1)
val (prefix,suffix) = nums.partition( _ == 1) // prefix = List(1,1,1,1), suffix = List(2,3,2)de&
padTo(len: Int, elem: A): List[A]
将列表扩展到指定长度,长度不够的时候,使用elem进行填充,否则不做任何操作。
& val nums = List(1,1,1)
val padded = nums.padTo(6,2)
// List(1,1,1,2,2,2)de&
18.combinations,permutations
combinations: combinations(n: Int): Iterator[List[A]] 取列表中的n个元素进行组合,返回不重复的组合列表,结果一个迭代器
permutations: permutations: Iterator[List[A]] 对列表中的元素进行排列,返回不重得的排列列表,结果是一个迭代器
&val nums = List(1,1,3)
val combinations = nums.combinations(2).toList //List(List(1,1),List(1,3))
val permutations = nums.permutations.toList
// List(List(1,1,3),List(1,3,1),List(3,1,1))de&
19.zip, zipAll, zipWithIndex, unzip,unzip3
zip: zip[B](that: GenIterable[B]): List[(A, B)] 与另外一个列表进行拉链操作,将对应位置的元素组成一个pair,返回的列表长度为两个列表中短的那个
zipAll: zipAll[B](that: collection.Iterable[B], thisElem: A, thatElem: B): List[(A, B)] 与另外一个列表进行拉链操作,将对应位置的元素组成一个pair,若列表长度不一致,自身列表比较短的话使用thisElem进行填充,对方列表较短的话使用thatElem进行填充
zipWithIndex:zipWithIndex: List[(A, Int)] 将列表元素与其索引进行拉链操作,组成一个pair
unzip: unzip[A1, A2](implicit asPair: (A) ? (A1, A2)): (List[A1], List[A2]) 解开拉链操作
unzip3: unzip3[A1, A2, A3](implicit asTriple: (A) ? (A1, A2, A3)): (List[A1], List[A2], List[A3]) 3个元素的解拉链操作
&val alphabet = List("A",B","C")
val nums = List(1,2)
val zipped = alphabet zip nums
// List(("A",1),("B",2))
val zippedAll = alphabet.zipAll(nums,"*",-1)
// List(("A",1),("B",2),("C",-1))
val zippedIndex = alphabet.zipWithIndex
// List(("A",0),("B",1),("C",3))
val (list1,list2) = zipped.unzip
// list1 = List("A","B"), list2 = List(1,2)
val (l1,l2,l3) = List((1, "one", '1'),(2, "two", '2'),(3, "three", '3')).unzip3
// l1=List(1,2,3),l2=List("one","two","three"),l3=List('1','2','3')de&
slice(from: Int, until: Int): List[A] 提取列表中从位置from到位置until(不含该位置)的元素列表
&val nums = List(1,2,3,4,5)
val sliced = nums.slice(2,4)
//List(3,4)de&
21.sliding
sliding(size: Int, step: Int): Iterator[List[A]] 将列表按照固定大小size进行分组,步进为step,step默认为1,返回结果为迭代器
&val nums = List(1,1,2,2,3,3,4,4)
val groupStep2 = nums.sliding(2,2).toList
//List(List(1,1),List(2,2),List(3,3),List(4,4))
val groupStep1 = nums.sliding(2).toList //List(List(1,1),List(1,2),List(2,2),List(2,3),List(3,3),List(3,4),List(4,4))de&
22.updated
updated(index: Int, elem: A): List[A] 对列表中的某个元素进行更新操作
&val nums = List(1,2,3,3)de&
val&fixed = nums.updated(3,4)&// List(1,2,3,4)
阅读(...) 评论() &

我要回帖

更多关于 scala 可变map 的文章

 

随机推荐