开发者学堂课程【Scala 核心编程-基础:惰性函数】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8937
惰性函数
内容介绍
一、含义
二、大数据推荐系统
三、惰性函数的由来
四、总结
一、含义
惰性函数听其名而知其意,首先它是一个函数,第二它是一个惰性函数。为什么要有惰性函数?将来做大数据处理时要处理很多数据,但是有可能处理完了之后,用户不用。
在阿贾克斯技术还没有出现的时候,所有的门户网站是打开首页面,把整个页面全部加载。一个首页面的内容很多,但实际上用户打开首页面以后,可能就看了暂时显示的页面,后面加载的就浪费了。这种场景在大数据计算里面也有可能是出现的。惰性计算的一种优化是延迟表达式的求值。
延迟表达式就是许多函数式编程语言的特性。惰性集合在需要时提供其他元素,无需预先计算。这样就带来一些好处,首先可以将耗时的计算推迟到绝对需要时再去计算。
在学 habit 的时候就有一个延时加载,是需要在进行页面渲染的时候它才去数据库查询这个程序。就类似于这推迟到绝对需要时才计算。这样就可以创造无限多个集合,只要继续接收请求,就会继续提供元素。函数的惰性能够得到更高效的代码。
java 没有惰性,没有提供惰性的原生支持,但 Scala 直接提供了,这个就叫惰性函数。
二、大数据推荐系统
1.大数据生态体系:
它主要完成了最主要的核心功能,就是完成三个功能。一个就是对数据的采集,kafka 就是在这里出现的。第二个就是对大数据的存储。第三个就是对大数据的计算。
大数据主要解决三个问题,最麻烦的是当采集到很多数据的时候,要马上计算。如果把数据马上计算出来,把它放到这个业务层,入库了但是别人不用。所以这边就出现一个在计算和存储之间能不能做一个缓冲的问题。先把数据存到对方,如果真的要计算,再调用 spark 进行实时计算,最后把这个结果用 javaEE 的技术展现给用户。这就是一个优化。
2.案例说明
京东准备做一个推荐系统。这儿有很多用户,这个用户在京东网站上买了很多的产品,买了很多产品就形成日志。日志有了后就用相应的技术进行采集。按理说采集完了过后就会发给 spark 进行一个实时计算。然后把结果推给javaEE 最后入库,或者是到文件最后用 javaEE 技术提供给用户就看到相应的推荐的产品了。
比如买了一双鞋子。买完之后它的下面就会展现出还可以购买其他的商品。但这种应用是实时的,有些应用场景这样做不合理,因为这个数据量会非常大。可以先把它缓冲到这个地方去,等到用户真的要用其中一个结果时,马上调用去进行计算。这个就是惰性函数的一个由来。
三、惰性函数的由来
1.核心代码:
Java 没有原生态的懒加载机制,它一般是通过自己的函数来实现。比如学 java 的时候,一定学过单例模式的懒汉式。还有一个叫饿汉。懒汉式核心代码大致就是:
if(property==null){
property=initProperty();
}
return property;
去加载一个类的时候,这个类并没有去真正的构建这个单位对象。比如调用 get property 时,如果为空,再去初始化对象。这个就是它核心的代码,这是 java 要自己去实现懒加载。
当函数返回值被声明为 lazy 时函数的执行将会被推迟,直到首次取或者是用这个返回值,该函数才会真正的执行。这个函数称之为惰性函数。
2.懒加载:
java 将这些框架代码称作为懒加载。新建一个包叫做 lazyDemo01。
Object LazyDemo01{
def main(args: Array[String]):Unit = {
Lazy val res = sum(10,20)
println(
“
---------
”
)
println(
“
res=
”
+res)
//在要使用 res 前才执行
}
//sum 函数,返回和
def sum (n1:Int,n2:Int):int={
println(
“
sum()执行了..
”
)
//输出一句话
return n1+n2
}
}
3.注意
(1)lazy 不能修饰 var 类型的变量
(2)不但是调用函数时加了 lazy 会导致函数的执行被推迟,在声明一个变量时如果声明了 lazy 那么变量值的分配也会推迟。比如 lazy var i=10。
数据计算出什么时候用?根据业务逻辑,希望有大量的计算。但是这个计算根据你的业务逻辑判断,可能并不是实时,马上就要把这个结果给他推过去。而是在用户使用的时候,在临时的基础上是可以的。而且 spark 的本身的特点就是它是内存级的计算框架,它本身计算速度就很快。即使刚刚加载进去也是秒级反应,所以没有必要非得把一大堆数据的结果都先入库。
将来的应用场景是如果有一个大数据的计算,但是你希望延迟到当用户调用时间。去计算的时候把函数给他加一个性能就会大大提升。
加一个 lazy 起这么大的效果,其实有时候优化就是那么少。
一个数据通道,类似于 QQ 服务器,那个服务器要支撑1000万人同时在线,目标并不大,但是要求只能在普通PC服务器上。里面最核心最耗费资源的是保存和查询用户在线状态这个功能。两个人聊天,比如 QQ 聊天的时候,要知道这个人有没有在线,有没有离线他的IP在什么地方,要发一个 hello 怎么给他传过去。其中有一个最核心的就是必须要在服务器拿到这个人的在线动态。那么客户端是每隔5秒或者10秒会向服务器报告他的状态。不报告服务器是不知道在线还是离线的。手机为什么有辐射?因为它每隔一定时间会向离它最近的这个基站发一个信息。到云南去,为什么打电话那边就能通。因为中国移动、中国联通有个服务器中心,每个手机或者客户端走了过后,他会向最近的那个基站报告。
因为大家都走服务器,将来写即时通讯软件也是一个道理。其中最耗费资源的就是怎么知道这个人在线。比如 A 好友有100个用户在线,那么一百个好友在线状态要实时更新,把每一个用户每隔5秒报告状态,直接写在 mysql 数据库里。优化其实没有那么难。包括以后大数据的优化,可能就是一个小技巧。
四、总结
1.惰性计算
惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们,这带来了一些好处。首先,您可以将耗时的计算推迟到绝对需要的时候。其次,您可以创造无限个集合,只要它们继续收到请求,就会继续提供元素。函数的情性使用让您能够得到更高效的代码。Java 并没有为情性提供原生支持,Scala 提供了。
2.大数据推荐系统
3.Java 实现懒加载的代码
public class LazyDemo {
private String property;
//属性也可能是一个数据库连接,文件等资源
public String getProperty() {
if(property== null){
//如果没有初始化过,那么进行初始化 property = initProperty();
}
return property;
}
private String initProperty() {
return"property";
}
}
//比如常用的单例模式懒汉式实现时就使用了上面类似的思路实现
4.惰性函数
(1)介绍
当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到首次对此取值,该函数才会执行。这种函数称之为惰性函数,在 Java 的某些框架代码中称之为懒加载(延迟加载)。
(2)案例演示
def main(args: Array[String]): Unit =
{
lazy val res = sum(10, 20)
println("
------
-")
print
l
n("res="+ res)
//在要使用 res 前,才执行
def sum(n
1
:
Int, n2 : Int): Int =
{
printIn("sum() 执行了..")
return n1 + n2
}
(3)注意事项和细节
lazy 不能修饰 var 类型的变量。
不但是在调用函数时,加了 lazy,会导致函数的执行被推迟,在声明一个变量时,如果给声明了 lazy,那么变量值的分配也会推迟。 比如lazy val i= 10