Java 在循环中使用if语句的最佳方式是什么?
我有一张清单需要处理。这些项目要么已启用,要么已禁用。用户可以选择是否显示禁用的项目 因此,您有依赖于项目的Java 在循环中使用if语句的最佳方式是什么?,java,optimization,if-statement,Java,Optimization,If Statement,我有一张清单需要处理。这些项目要么已启用,要么已禁用。用户可以选择是否显示禁用的项目 因此,您有依赖于项目的cond2,而没有依赖于项目的cond1。我陷入了两难境地:我应该使用cond1&&!cond2或!(!cond1 | | cond2)?或者我应该在循环之前检查cond2(显示禁用项)?我还想(正如你在我所写的代码中看到的那样)我是否应该把cond2放在cond1之前,因为cond2 是一个布尔变量,使用“短路”(惰性计算?)会更快吗 我主要关心的是速度。如果循环中有许多项,这可能是一个
cond2
,而没有依赖于项目的cond1
。我陷入了两难境地:我应该使用cond1&&!cond2
或!(!cond1 | | cond2)
?或者我应该在循环之前检查cond2
(显示禁用项)?我还想(正如你在我所写的代码中看到的那样)我是否应该把cond2
放在cond1
之前,因为cond2
是一个布尔变量,使用“短路”(惰性计算?)会更快吗
我主要关心的是速度。如果循环中有许多项,这可能是一个重要的更改
这是说明选项的代码:
// First Option
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item) && !showDisabled) {
continue;
}
doSomethingElse(item);
}
// Second Option
for (String item : items) {
doSomethingFirst(item);
if (!(!isDisabled(item) || showDisabled)) {
continue;
}
doSomethingElse(item);
}
// Third Option
if (showDisabled) {
for (String item : items) {
doSomethingFirst(item);
doSomethingElse(item);
}
} else {
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item)) {
continue;
}
doSomethingElse(item);
}
}
那么,isDisabled(item)
和showdabled
的顺序是否重要?我应该在循环之前检查一下吗?还是编译器优化了它?(我怀疑……)
PS我不知道如何进行测量以查看实际值,如果相关,请进行测量
谢谢。对于这些类型的问题,您应该衡量这一点,以确定这本身是否是您的瓶颈。如果是的话,那么我会衡量替代方案。我怀疑在上述情况下,它几乎不会对您的备选方案产生任何影响,特别是因为您可能会对列表项进行更为重要的操作(显示它们?将它们写入数据库或文件?)
衡量这一点的最简单方法是生成一个相当大的列表,在处理之前记录时间(例如,通过System.currentTimeMillis()),然后记录所用的毫秒(或秒) 在Java中,表达式从左到右求值。如果第一个条件为假,则不执行第二个条件;如果第一个条件为真,则不执行第二个条件 因此,在您的情况下,请尝试将可以更快解决的条件放在首位
showdabled
对于第三个例子,它看起来更好,因为您只检查了一次布尔值,但我想它不会真正改变性能,布尔值比较并不是非常昂贵。在代码的其他部分,您可能会有更好的改进。(就可读性而言,这不是我最喜欢的——相当长)
如果您想测量您案例中的性能,请使用探查器
或添加您的代码:
long start=System.currentTimeMillis();
//code to analyse
long timeSpent = System.currentTimeMillis()-start
您必须将代码放入一个循环中,以使其具有相关性。您可能会注意到,经过一些循环之后,Java将提高性能;)
我应该使用cond1&!康多尔!(!cond1 | | cond2)?或者我应该在循环之前检查cond2(显示禁用项)
最能表达你思想的东西,即更具可读性的东西
我主要关心的是速度
写作速度?重构速度?编译速度?发展速度?阅读和理解速度?调试速度?执行速度
你不可能一次拥有全部。没有语言。我将选择选项1,只需反转开关
isDisabled(item) && !showDisabled
与
如果isDisabled(…)
和您说的一样慢,那么最好先测试更快的情况。
现在,与其他选项相比,这是最明确和可读的:
- 我们为所有项目都做了一些事情
- 我们跳过验证某些测试的项目
- 我们为所有其他项目做一些事情李>
很难做到更明确。第三个选项非常难看。关于可读性,另一个好的做法是将函数和变量命名为正状态。双重否定很难理解。你喜欢读哪一本
enabled
或
虽然在一些情况下,以否定的形式命名事物是有意义的。例如,如果您将它们用于终止条件,例如文件结束<代码>而(!feof(fp))
但在大多数情况下,规范应该是以积极的形式命名,因此阅读代码的摩擦较小
让我们看看您的代码是如何以正数形式显示的:
// First Option
for (String item : items) {
doSomethingFirst(item);
// if (isDisabled(item) && !showDisabled) {
if (!isEnabled(item) && showEnabled) {
continue;
}
doSomethingElse(item);
}
该代码的可读性肯定有所提高
即使下面的内容也变得可读,双重否定是可以避免的,阅读代码实际上只是阅读它,而不是过多地理解它。我曾经读过一篇文章,其中建议在编写代码时,阅读也应该非常愉快,他说阅读代码不应该像阅读侦探小说一样。阅读双重否定密码就像阅读和破译侦探小说
// Second Option
for (String item : items) {
doSomethingFirst(item);
// if (!(!isDisabled(item) || showDisabled)) {
// You can now avoid double negatives
if (!( isEnabled(item) || !showEnabled )) {
continue;
}
doSomethingElse(item);
}
事实上,以下不仅仅是双重否定,而是三重否定:
如果(!(!isDisabled(项目)
需要两次读取,甚至三次读取才能破译该代码的意图所以你是说选项1和2是相似的,只要先计算常数?从意义上看是一样的,但从速度上看也是一样的?是的,在这种情况下是一样的,但第二个选项读起来很糟糕;)如果if语句中没有对性能产生影响的大量方法调用,请选择可读性最好的方法。实际上,我担心
isDisabled
可能会很慢…这就是条件本身…我将尝试进行测量。这不重要。选择可读性最好的方法。@delnan我会想到第三个选项更快,不是吗?但我会重复我自己。所以可读性--;如果你做了一个微基准测试,它可能会更快。它也可能会更慢-例如,由于CPU缓存,JVM优化可能会优化一个循环,但忽略了另一个,内联可能会因为代码膨胀而被阻止-所以我拒绝猜测。但是,我99%确信任何差异都会太大购物中心为你花在思考和做这件事上的时间(n
// First Option
for (String item : items) {
doSomethingFirst(item);
// if (isDisabled(item) && !showDisabled) {
if (!isEnabled(item) && showEnabled) {
continue;
}
doSomethingElse(item);
}
// Second Option
for (String item : items) {
doSomethingFirst(item);
// if (!(!isDisabled(item) || showDisabled)) {
// You can now avoid double negatives
if (!( isEnabled(item) || !showEnabled )) {
continue;
}
doSomethingElse(item);
}