当前位置: 首页 > 面试题库 >

经典运算枚举示例中的Lambda

芮念
2023-03-14
问题内容

众所周知,有一个经典的Operation枚举示例(尽管现在使用Java 8标准接口),如下所示:

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

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

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);
    }
}

从功能上讲,它是等效的,但是两种实现方式是否仍然相似,或者是否存在一些隐藏的细节使新版本比旧版本更糟?

最后,从Java 8开始,lambda方法是否是首选方法?


问题答案:

显然,lambda版本更具可读性。它不仅更短,而且还使读者乍一看构造函数中的实现操作符。假设您也想扩展enum来支持int计算…

从性能的角度来看,您正在enum通过生成的lambda类交换匿名内部类。lambda版本增加了另一级别的委派,但这对HotSpot优化器来说不是挑战。在执行性能方面几乎看不出任何差异。

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

总结一下:

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

因此,这对于lambda是一个巨大的胜利。是的,我认为lambda方式是Java 8的首选方式。



 类似资料:
  • 我知道我们使用来迭代列表,但我在字典上试过了,它没有给出错误。 代码: 输出: 有人能解释一下输出吗?

  • 枚举 在实际问题中, 有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月, 一个班每周有六门课程等等。如果把这些量说明为整型, 字符型或其它类型显然是不妥当的。 为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值, 被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是, 枚举类型是一种基本数据类型,而不是一种构造类型,

  • 问题内容: 这不是卡住我的问题,而是我正在寻找一种编写代码的整洁方法。 本质上,我正在编写一个事件驱动的应用程序。用户触发一个事件,该事件被发送到适当的对象,然后这些对象处理事件。现在,我正在编写偶数处理程序方法,并且希望使用switch语句确定如何处理事件。现在,在我研究通用结构时,事件类非常简单: 然后,在另一堂课中,我会看到类似以下内容的内容: 我会 喜欢 做的就是这样的事情(尽管我当然会坚

  • 问题内容: 这是我的简化课程和枚举。 如果我跑 一切都很好,花花公子。 但是,如果我执行以下操作: 我得到: 如果我做: 我得到: 有任何想法吗? 问题答案: 这应该做。

  • 错误:“运算符==”的重载不明确(操作数类型为“A”和“A”) 注:候选者:运算符==(A,A)内置 注:候选:布尔运算符==(常数A)