假设我有一个boolean
函数isCorrect(Set<Integer>)
函数的参数由另一个函数buildSet()
计算。
哪一项在时间和空间效率方面都更好?
Set<Integer> set = buildSet();
if(isCorrect(set))
doSomethingWith(set);
或
if(isCorrect(buildSet()))
doSomethingWith(buildSet());
答案 0 :(得分:4)
第一种方法更好,我不认为这是一个意见问题。当你已经有了它的结果时,不要浪费两次相同的功能。当然,我假设buildSet()
没有任何必要的副作用。
哪一项在时间和空间效率方面都更好?
就时间而言,您在第一个片段中构建了一次,在第二个片段中构建了两次,因此大概需要更长时间。在空间方面,可能没有区别。但是,您似乎在第二个片段中实例化了两个对象,而在您的第一个片段中只有一个(再次,我无法确定这一点,因为我不知道buildSet()
是怎样的实现)。如果是这种情况并且你保留了这两个对象,那么第二个片段也将使用两倍的空间。
答案 1 :(得分:1)
答案是 - 这取决于。见下文:
因此,总结一下:在大多数情况下,存储结果是有意义的。有时(但IMO不经常)它并不是真正的必要。
答案 2 :(得分:1)
虽然现有答案提供了很好的理由,为什么存储价值最好,但他们错过了我认为重要的一个(实际上,最重要的一个):在你的第二个例子中(两次运行该功能),你引入了潜在的竞争条件。
如果buildSet()
依赖于外部因素(在任何非平凡的函数中很可能 - 并且可能在以后的更改中变为真实),则if
检查之间的值可能会发生变化和第二个电话。这可能会创建一个微妙且难以找到的错误,当您在其他地方进行更改或某些事件在特定时间发生时,这些错误可能会变得可见。
这本身就是避免这种模式的一个很好的理由。
答案 3 :(得分:1)
通过从第二个示例(两个调用)转到第一个(一个调用),您将节省第二次调用buildSet
在堆栈上的时间。如果该呼叫在10%的时间内在堆栈上,则您的加速将是100/90 = 1.11或11%的因子。如果它在50%的时间内处于堆栈中,则加速将是100/50 = 2或100%的因子。
你如何知道函数调用在堆栈中的时间长度? 它是包含挂钟的逐行。
不是每个探查者都会告诉你这个。
buildSet
函数或应用程序的其他地方有任何I / O,睡眠或锁定等待,那么分析器的行为就像它没有存在。 告诉你的是Zoom。 其他人可能,如果你能弄明白如何告诉他们该做什么。 我和很多人使用的方法是random pausing。