[Java 8] (7) 利用Stream类型的"懒"操作

利用Stream类型的“懒”操作

代码中的很多操作都是Eager的,比如在发生方法调用的时候,参数会立即被求值。总体而言,使用Eager方式让编码本身更加简单,然而使用Lazy的方式通常而言,即意味着更好的效率。

本篇文章就是为了展示Java 8中新特性是如何让我们能够更方便的写出Lazy方式代码。

延迟初始化

对于会消耗较多资源的对象,使用延迟初始化是比较好的选择。这不仅能够节省一些资源,同时也能够加快对象的创建速度,从而从整体上提升性能。

但是对一个对象实现延迟初始化时,需要注意的一点就是这些实现细节不应该暴露给用户,即用户能够按照正常的流程来使用该对象。

典型实现

public class Heavy {
   
    public Heavy() {
    System.out.println("Heavy created"); }
    public String toString() {
    return "quite heavy"; }
}

public class HolderNaive {
   
    private Heavy heavy;
    public HolderNaive() {
   
        System.out.println("Holder created");
    }
    public Heavy getHeavy() {
   
        if(heavy == null) {
   
            heavy = new Heavy();
        }
        return heavy;
    }
    //...
}

利用以上的代码:

final HolderNaive holder = new HolderNaive();
System.out.println("deferring heavy creation...");
System.out.println(holder.getHeavy());
System.out.println(holder.getHeavy());

// Holder created
// deferring heavy creation...
// Heavy created
// quite heavy
// quite heavy

上述代码在单线程环境中能够正常工作,但是在多线程环境中就不尽然了。当多个线程同时调用getHeavy方法时,也许会发生竞态条件(Race Condition),导致有多个Heavy实例被创建,最直观的解决方案就是给该方法加上synchronized关键字:

public synchronized Heavy getHeavy() {
   
    if(heavy == null) {
   
        heavy = new Heavy();
    }
    return heavy;
}

这样虽然能够保证确实只有一个heavy实例被创建,但是弊端也很明显:每次调用getHeavy方法时,都需要进入代价高昂的synchronized代码区域。实际上,只有在第一次需要创建Heavy实例的时候,才需要保证线程安全。当该实例创建完毕之后,再使用synchronized来保证线程安全就没有必要了。

使用Lambda表达式

这里我们需要用到的是函数接口Supplier,其中定义了一个get方法用来得到需要的实例:

Supplier<Heavy> supplier = () -> new Heavy();
Supplier<Heavy> supplier = Heavy::new;

除了利用Lambda表达式来

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值