当前位置: 首页 > 知识库问答 >
问题:

将空检查替换为可选的

巫马越彬
2023-03-14
if (item!= null)
{
   if (item.getCrystal() == Crystal.A)
   {
     player.getInventory().addItem(inventoryItem);
   }
}

我喜欢的,我觉得很酷的东西

Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A).ifPresent(k -> player.getInventory.addItem(i));

有人能告诉我我没意见吗?也许很酷,但成本很高?我不知道.多谢.

共有1个答案

朱保赫
2023-03-14

在像这样的简单情况下,及时编译器可能会省略对象分配,或者至少在堆栈上分配对象,因此开销可以忽略不计。

这里有一个小基准:

public abstract class Benchmark {

    final String name;

    public Benchmark(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name + "\t" + time() + " ns / iteration";
    }

    private BigDecimal time() {
        try {
            // automatically detect a reasonable iteration count (and trigger just in time compilation of the code under test)
            int iterations;
            long duration = 0;
            for (iterations = 1; iterations < 1_000_000_000 && duration < 1_000_000_000; iterations *= 2) {
                long start = System.nanoTime();
                run(iterations);
                duration = System.nanoTime() - start;
                cleanup();
            }
            return new BigDecimal((duration) * 1000 / iterations).movePointLeft(3);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Executes the code under test.
     * @param iterations
     *            number of iterations to perform
     * @return any value that requires the entire code to be executed (to
     *         prevent dead code elimination by the just in time compiler)
     * @throws Throwable
     *             if the test could not complete successfully
     */
    protected abstract Object run(int iterations) throws Throwable;
    
    /**
     * Cleans up after a run, setting the stage for the next.
     */
    protected void cleanup() {
        // do nothing
    }

    public static void main(String[] args) throws Exception {
        Integer[] a = {null, -1, null, 1}; // mix nulls and real values
        
        System.out.println(new Benchmark("Optional") {
            @Override
            protected Object run(int iterations) throws Throwable {
                int[] sum = {0};
                for (int i = 0; i < iterations; i++) {
                    Optional.ofNullable(a[i & 3]).filter(k -> k > 0).ifPresent(k -> sum[0] += k);
                }
                return sum[0]; 
            }
        });
        System.out.println(new Benchmark("if != null") {
            @Override
            protected Object run(int iterations) throws Throwable {
                int[] sum = {0};
                for (int i = 0; i < iterations; i++) {
                    var k = a[i & 3];
                    if (k != null && k % 2 != 0) {
                        sum[0] += k; 
                    }
                }
                return sum[0]; 
            }
        });
    }
}

这表明,使用可选的开销大约为1 ns,即现代CPU每秒可以构造和计算大约10亿个可选对象。除了最极端和人为的工作负载之外,使用可选的对性能的影响不足以让人注意到。

if (item != null && item.getCrystal() == Crystal.A) player.getInventory().addItem(inventoryItem);
Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A).ifPresent(k -> player.getInventory.addItem(i));

当然,在实际代码中,您可能希望将行数保持得相当短,因此比较如下

if (item != null && item.getCrystal() == Crystal.A) {
    player.getInventory().addItem(inventoryItem);
}

VS

Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A)
    .ifPresent(k -> player.getInventory.addItem(i));

同样,我发现第一个版本更易读,因为它包含的单词更少。

 类似资料:
  • 下面是我的代码,按预期工作。但我需要用Optional.ofNullable替换它 如何使用

  • 我刚从Java7转到8,我的代码中到处都是代码片段,比如 我注意到,空检查有时被认为是一种反模式,而Java8提倡使用可选的。让我的代码看起来像这样有什么好处吗

  • 有人能解释一下<code>是可选的</code>如何帮助我们避免<code>NullPointerException</code>吗? 这段代码不是也容易出现<code>NullPointerException</code>吗?如果是这样的话,那么为什么这个代码比其他代码更受欢迎 除了帮助我们了解函数是否实际具有返回值之外,还提供了什么可能的好处

  • 有人能解释一下如何帮助我们避免? 这段代码不是也容易出现吗?如果是这样的话,那么为什么这个代码比 除了帮助我们了解函数是否实际具有返回值之外,还有什么可能的好处

  • 问题内容: 在Objective-C中,当我有一个数组时 我想检查它是否不为空,我总是这样做: 这样一来,无需检查是否会因为这种情况将导致代码陷入错误,并且非空数组也会这样做。 但是,在Swift中,我偶然发现了一个可选数组: 而且我无法确定要使用哪种条件。我有一些选择,例如: 选项A:在相同条件下检查非用例和空用例: 选项B: 使用解除绑定数组: 选项C: 使用Swift提供的合并运算符: 我不

  • 我正在开发一个使用返回的方法的程序,我需要迭代它并创建一个新对象。我该怎么做? 我对Java可选选项的理解是减少检查,但如果没有检查,我仍然无法做到这一点。使用或并拥有简洁的代码,有没有更好的解决方案?