经典操作枚举示例中的 Lambda [英] Lambdas in the classical Operation enum example

查看:35
本文介绍了经典操作枚举示例中的 Lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你们中的许多人可能知道,有一个 Operation 枚举的经典示例(尽管现在使用 Java 8 标准接口),如下所示:

As many of you may know, there is a classical example of the Operation enum (using Java 8 standard interface now though), that is the following:

enum Operation implements DoubleBinaryOperator {
    PLUS("+") {
        @Override
        public double applyAsDouble(final double left, final double right) {
            return left + right;
        }
    },
    MINUS("-") {
        @Override
        public double applyAsDouble(final double left, final double right) {
            return left - right;
        }
    },
    MULTIPLY("*") {
        @Override
        public double applyAsDouble(final double left, final double right) {
            return left * right;
        }
    },
    DIVIDE("/") {
        @Override
        public double applyAsDouble(final double left, final double right) {
            return left / right;
        }
    };

    private final String symbol;

    private Operation(final String symbol) {
        this.symbol = symbol;
    }

    public String getSymbol() {
        return symbol;
    }
}

测试:

Arrays.stream(Operation.values())
        .forEach(op -> System.out.println("Performing operation " + op.getSymbol() + " on 2 and 4: " + op.applyAsDouble(2, 4)));

它提供:

在 2 和 4 上执行操作 +:6.0
执行操作 - 在 2 和 4 上:-2.0
在 2 和 4 上执行操作 *:8.0
在 2 和 4 上执行操作/:0.5

Performing operation + on 2 and 4: 6.0
Performing operation - on 2 and 4: -2.0
Performing operation * on 2 and 4: 8.0
Performing operation / on 2 and 4: 0.5

但我觉得我们可以用 Java 8 做得更好,因此我实现了以下内容:

But I feel like we can do better with Java 8, hence I implemented the following:

enum Operation implements DoubleBinaryOperator {
    PLUS    ("+", (l, r) -> l + r),
    MINUS   ("-", (l, r) -> l - r),
    MULTIPLY("*", (l, r) -> l * r),
    DIVIDE  ("/", (l, r) -> l / r);

    private final String symbol;
    private final DoubleBinaryOperator binaryOperator;

    private Operation(final String symbol, final DoubleBinaryOperator binaryOperator) {
        this.symbol = symbol;
        this.binaryOperator = binaryOperator;
    }

    public String getSymbol() {
        return symbol;
    }

    @Override
    public double applyAsDouble(final double left, final double right) {
        return binaryOperator.applyAsDouble(left, right);
    }
}

功能上是等价的,但是两者的实现还是相似的,还是有一些隐藏的细节使新版本不如旧版本?

Functionally it is equivalent, however are both implementations still similar, or are there some hidden details that make the new version worse as the old version?

最后,从 Java 8 开始,lambda 方式是首选方式吗?

And lastly, is the lambda way the preferred way to do it as of Java 8?

推荐答案

显然,lambda 版本更具可读性.它不仅更短,而且允许读者第一眼看到构造函数中的实现运算符.假设您想扩展 enum 以支持 int 计算以及...

Obviously, the lambda version is far more readable. Not only is it shorter, it allows a reader to see the the implementation operator at the first glance in the constructor. Imagine you want to extend the enum to support int calculation as well…

从性能的角度来看,您正在通过生成的 lambda 类交换匿名 enum 内部类.lambda 版本增加了另一个级别的委托,但这对 HotSpot 优化器没有挑战.不太可能在执行性能方面看到任何差异.

From a performance point of view you are exchanging the anonymous enum inner classes by generated lambda classes. The lambda version adds another level of delegation but that’s no challenge to the HotSpot optimizer. It’s unlikely to see any difference regarding the execution performance.

然而,当应用 lambda 模式时,您可能会获得使用该类的应用程序启动的加速.原因是对于传统的专用 enum 方法,Java 编译器必须为驻留在文件系统或(可能是 zip 压缩的)Jar 文件中的每种情况生成一个内部类.动态生成 lambda 类(具有非常简单的结构)的字节码通常比加载类更快.没有对生成的 lambda 类进行访问检查也可能有所帮助.

However, when applying the lambda pattern consequently you might get a speedup of the startup of applications using the class. The reason is that for the traditional specialized enum approach the Java compiler has to generate an inner class for each case which resides either in the file system or (possibly zip-compressed) in a Jar file. Generating the byte code for a lambda class (which has a very simple structure) on the fly is usually faster than loading a class. It might help as well that there is no access checking for the generated lambda classes.

总结一下:

  • lambda 方法更易于阅读,其代码更易于维护(重点)
  • 执行性能大致相同
  • lambda 方法的启动时间可能更短

所以这是 lambda 的一大胜利.是的,我认为 lambda 方式是从 Java 8 开始的首选方式.

So it’s a big win for the lambda. Yes, I think the lambda way the preferred way to do it as of Java 8.

这篇关于经典操作枚举示例中的 Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆