最近,我开始为实习工作做一个与大数据相关的新项目。我的经理建议开始学习函数式编程(他们强烈推荐Scala)。我有过使用F#的卑微体验,但我看不出使用这种编程范式的重要性,因为在某些情况下它很昂贵。
迪恩就这个话题发表了一篇有趣的演讲,并分享了他对为什么“大数据”在这里:http://www.youtube.com/watch?v=DFAdLCqDbLQ的想法,但并不是很方便,因为大数据并不意味着只有Hadoop。
因为BigData是一个非常模糊的概念。我暂时忘了它。我试着拿出一个简单的例子来比较我们处理数据的不同方面,看看功能方式是否昂贵。如果函数式编程是昂贵的,小数据的内存消耗,为什么我们需要它来处理大数据呢?
我试图用三种方法构建一个特定且流行的问题的解决方案:命令式方法和函数式方法(递归,使用集合),而不是花哨的工具。我比较了时间和复杂性,比较了这三种方法。
我用Scala编写了这些函数,因为它是使用三种范式编写算法的最佳工具
def main(args: Array[String]) {
val start = System.currentTimeMillis()
// Fibonacci_P
val s = Fibonacci_P(400000000)
val end = System.currentTimeMillis()
println("Functional way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s, end - start))
val start2 = System.currentTimeMillis()
// Fibonacci_I
val s2 = Fibonacci_I(40000000 0)
val end2 = System.currentTimeMillis();
println("Imperative way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s2, end2 - start2))
}功能方式:
def Fibonacci_P(max: BigInt): BigInt = {
//http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
//lazy val Fibonaccis: Stream[Long] = 0 #:: 1 #:: Fibonaccis.zip(Fibonaccis.tail).map { case (a, b) => a + b }
lazy val fibs: Stream[BigInt] = BigInt(0)#::BigInt(1)#::fibs.zip(fibs.tail).map {
n = > n._1 + n._2
}
// println(fibs.takeWhile(p => p < max).toList)
fibs.takeWhile(p = > p < max).foldLeft(BigInt(0))(_ + _)
}递归方式:
def Fibonacci_R(n: Int): BigInt = n match {
case 1 | 2 = > 1
case _ = > Fibonacci_R(n - 1) + Fibonacci_R(n - 2)
}命令式方式:
def Fibonacci_I(max: BigInt): BigInt = {
var first_element: BigInt = 0
var second_element: BigInt = 1
var sum: BigInt = 0
while (second_element < max) {
sum += second_element
second_element = first_element + second_element
first_element = second_element - first_element
}
//Return
sum
}我注意到函数式编程太重了!它需要更长的时间和更多的内存空间。我很困惑,每当我读一篇文章或看一次演讲,他们说我们应该在数据科学中使用函数式编程。的确,S更容易,更有效率,特别是在数据世界。但它需要更多的时间和更多的内存空间。
那么,为什么我们需要在大数据中使用函数式编程呢?对大数据使用函数式编程(Scala)的最佳实践是什么?
发布于 2013-12-07 15:00:34
以下是我的看法:
MapReduce是一个在集群上使用并行分布式算法处理大型数据集的编程模型。
..。
一个MapReduce程序由一个Map()过程组成,该过程执行过滤和排序(例如将学生按名字排序到队列中,每个名字有一个队列)和一个Reduce()过程,该过程执行摘要操作(例如计算每个队列中的学生数量,产生名称频率)。
..。
“MapReduce”是一个使用大量计算机处理大型数据集中可并行性问题的框架。
同样在本页中,Hadoop被描述为
Hadoop,Apache的免费开源MapReduce实现。
现在,Hadoop是用Java编写的,Java不是函数式语言。另外,如果我们查看Hadoop的页面,我们也会发现一个如何在Java中创建MapReduce作业并将其部署到Hadoop集群的示例。
下面是一个用于Hadoop的Fibonnaci MapReduce作业的Java示例。
我希望这个问题能够回答您的问题,即BigData,特别是创建斐波纳契的MapReduce作业“不需要”具有功能,也就是如果您愿意,可以用OO语言实现它(例如)。
当然,这并不意味着BigData“需要”成为OO--也不是唯一的。您可以很好地使用函数式语言来实现类似于MapReduce的作业。例如,您可以通过烫伤将Scala与Hadoop结合使用。
我认为还有几点值得提及。
在Scala中执行递归时,如果代码允许,Scala将执行尾叫优化。但是,由于JVM还不支持尾叫优化,Scala通过在编译时用相当于循环如前所述的代码替换递归调用来实现这一点。这基本上意味着使用Scala执行递归和非递归代码基准测试是没有意义的,因为它们最终都在运行时完成相同的任务。
发布于 2013-12-07 13:53:23
只要你能在一台机器上运行它,它就不是“大数据”。您的示例问题完全不适合演示有关它的任何内容。
大数据意味着问题规模太大,分配处理不是优化,而是一项基本要求。而函数式编程由于数据结构的不可变性和无状态性,使得编写正确有效的分布式代码变得更加容易。
发布于 2017-12-01 17:51:30
如果函数式编程是昂贵的,小数据的内存消耗,为什么我们需要它来处理大数据呢?
具体来说,我已经看到了一些非常有用的应用程序。例如。统计,即用不同的参数或一组用于数据分析的参数动态计算高斯函数。数值分析也有插补等。
对大数据使用函数式编程(Scala)的最佳实践是什么?
要回答效率问题,还有一些技术可以帮助提高您在空间或时间上的效率,特别是递归、尾递归、延拓传递方式、高阶函数等。有些语言有其优点和缺点(例如懒惰和渴望)。对于像Fibonnacci序列这样简单的东西,我可能会像我有时发现的那样使用祈使方式,我的一些同事不愿意使用函数编程,因此占用了更多的开发时间。(当我可以使用我负责的申请时,我仍然倾向于使用函数式编程),因为我发现它是快速、干净和“易于阅读”的(尽管我发现这是主观的)代码。
维基百科发布了斐波纳契序列的“快速”版本。https://en.wikipedia.org/wiki/Functional_programming#Scala
def fibTailRec(n: Int): Int = {
@tailrec def f(a: Int, b: Int, c: Int): Int = if (a == 0) 0 else if(a < 2) c else f(a-1, c, b + c)
f(n, 0, 1)
}使用流/hof
val fibStream:Stream[Int] = 0 #:: 1 #:: (fibStream zip fibStream.tail).map{ t => t._1 + t._2 }https://softwareengineering.stackexchange.com/questions/220605
复制相似问题