这两个片段之间有什么区别吗?性能?可读性?否则?
if (arg > 0) {
for (int i = 0; i < arg; i++) {
sb.append(">");
}
} else if (arg < 0) {
for (int i = 0; i < Math.abs(arg); i++) {
sb.append("<");
}
}
for (int i = 0; i < Math.abs(arg); i++) {
if (arg > 0) {
sb.append(">");
} else if (arg < 0) {
sb.append("<");
}
}
就个人而言,我更喜欢前者,因为它更清楚地表明arg
是常数。
答案 0 :(得分:3)
我说两者都很不可读。无论如何,关于速度:
好处是JIT喜欢简单易读的代码。
我只是为了
for (int i = 0; i < Math.abs(arg); i++) sb.append(arg > 0 ? ">" : "<");
并希望
arg
是一个循环不变量Math.abs(arg)
只会评估一次arg > 0 ? ">" : "<"
如果我在优化后感到疯狂,我会写
char c = arg > 0 ? '>' : '<'; // char instead of String
for (int i = Math.abs(arg); i > 0; i--) sb.append(x);
但实际上有一个Guava解决方案:
sb.append(Strings.repeat(arg > 0 ? ">" : "<", Math.abs(arg));
答案 1 :(得分:2)
如果你说arg
是一个常量,那么前者会更有效率,因为你只评估if / else条件一次,而不是每次循环迭代时都要评估它。但是,如果arg在每次循环迭代中都不是常量,那么你显然想要使用后者。
答案 2 :(得分:2)
我不会使用其中任何一个;我会尝试下面两个片段中的一个。
第一个变体
char c = arg > 0 ? '>' : '<';
int n = Math.abs(arg);
StringBuffer sb = new StringBuffer(n);
for (int i = 0; i < n; ++i) {
sb.append(c);
}
在这里,我的建议是:
首选对象的基元(char
可能比String
更快。)
如果您已经知道尺寸(通过调用StringBuffer(int n)
),请预先分配缓冲区。
首选无分支循环(更好的可读性,维护性和速度)。
第二个变体
char c = arg > 0 ? '>' : '<';
int n = Math.abs(arg);
char[] content = new char[n];
Arrays.fill(content, c);
StringBuffer sb = new StringBuffer(n);
sb.append(content);
在这里,我的建议是:
首选算法自编循环(上面的代码片段根本没有循环)。
特别是,System.arraycopy()
(由sb.append(char[] )
调用)是一种本机方法,不会在每次迭代中执行绑定检查。
我个人更喜欢这个第二版,因为它是无环路的。它的缺点是它分配和触摸与content
对应的内存两次:首先填充content
,然后将其复制到StringBuffer
。
最重要的是,对您的代码进行分析,以确保您没有premature optimization。
“想要速度?测量。”(Howard Hinnant)
答案 3 :(得分:1)
如果arg
小于0,则不会运行循环,因为i
在开始时等于0,当然不小于0.
因此,如果arg
小于0,则第二个选项会变慢,因为它会遍历所有选项,而不管它是否真实。
答案 4 :(得分:1)
我不喜欢他们中的任何一个:
Math.abs()
。arg
为否定,它将不会终止。所以它在任何情况下都不等同于第一个。所以你要比较苹果和橘子。