使用多个对象或者大数据结构时,一种提升其性能的方式是运用延迟加载或赋值(来实现)。将费时的操作尽可能的缩短的想法,从未实现。我通过一些例子来说明延迟加载技术在Java中如何运用,给予一些指引以在其他语言中能更易(使用)并作为核心语言的一部分。
一种使用场景是通过JTable来展示数百个包含元数据和测量值得域对象。初始化我们的域对象在内存中能保存两种类型的对象,即便在表格中仅显示部分元数据。构建该表格将花费数秒钟的时间,(但)我们可以接受再次展示数百项(数据)。在做了一些分析过后,我们改进了我们的实现,看起来像这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class DomainObject { private final DataParser parser; private final Map<String, String> header = new HashMap<>(); private final List<Data> data = new ArrayList<>(); public DomainObject(DataParser aParser) { parser = aParser; } public String getHeaderField(String name) { // Here we lazily parse and fill the header map if (header.isEmpty()) { header.addAll(parser.header()); } return header.get(name); } public Iterable<Data> getMeasurementValues() { // again lazy-load and parse the data if (data.isEmpty()) { data.addAll(parser.measurements()); } return data; } } |
这种改进改善了显示时间的条目和显著提高了我们处理大数据项的(能力)。所有的数据载入仅在有人想查看测量的具体细节和双击某条目时才会发生。
一种java拆箱后得到延迟赋值在条件语句的情况下
1
2
3
4
5
|
// lazy and fast because the expensive operation will only execute when needed if (aCondition() && expensiveOperation()) { ... } // slow order (still lazy evaluated!) if (expensiveOperation() && aCondition()) { ... } |
持久层框架像Hibernate时常默认延迟加载是因为在通常情况下数据库访问并且数据传送代价相当高昂。
大多数语言功能是基于环绕延迟赋值的情况下这种理论上的功能如同第一个类所有成员最大程度上隔离降低副作用对延迟的影响。Scala混合了面向对象语言功能并引进延迟关键字简化了java样式,延迟初始代码就像下面这样
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class DomainObject(parser: DataParser) { // evaluated on first access private lazy val header = { parser.header() } def getHeaderField(name : String) : String = { header.get(name).getOrElse( "" ) } // evaluated on first access lazy val measurementValues : Iterable[Data] = { parser.measurements() } } |
结论
延迟加载不是新的革命性技术但当处理大数据或放慢资源却是一个非常有用的工具。在这些很多情况下你能使用它提升性能或使用者亲身经历使用它。
它可以降低实现代码的成本如果语言支持不是很好(像java)和其它一些情况的下应用就要在预编译预处理情况下感受更多的响应。