英文:
Why is String-String concatenation quicker than String-long concatenation?
问题
在`Java`中,以下代码:
long x = 123;
String s = "abc" + x;
比起以下代码要运行时间显著更长:
long x = 123;
String s = "abc" + String.valueOf(x);
我是通过LeetCode了解到这一点的。我当时正在尝试解决以下问题:https://leetcode.com/problems/fraction-to-recurring-decimal/
以下是我解决方案的确切代码:
```java
public String fractionToDecimal(int numerator, int denominator) {
long n = numerator, d = denominator;
boolean isNegative = (n * d < 0);
if (n < 0) n = -n;
if (d < 0) d = -d;
long q = n / d;
long r = n % d;
if (r == 0) return (isNegative ? "-" : "") + q;
StringBuilder sb = new StringBuilder();
if (isNegative) sb.append('-');
sb.append(q).append('.');
Map<Long, Integer> found = new HashMap<>();
int index = sb.length();
while (r > 0 && !found.containsKey(r)) {
found.put(r, index++);
n = r * 10;
q = n / d;
r = n % d;
sb.append(q);
}
if (r > 0) {
sb.insert(found.get(r), "(");
sb.append(')');
}
return sb.toString();
}
当我点击提交
按钮时,完成所需时间长达7毫秒。但如果我只是将第8行从+ q
更改为+ String.valueOf(q)
,运行时间会降至仅1毫秒。如果需要的话,可以随意将代码复制粘贴到LeetCode上,以便在那里尝试并亲自查看运行时的变化。
这对我来说非常令人困惑。为什么会发生这种情况呢?按照我的理解,在这两种情况下,编译器首先将long
转换为String
,然后将这两个String
连接在一起,对吗?那么,在底层,连接一个String
和一个long
难道不与连接两个String
完全相同吗?那么为什么一个运行时间比另一个长呢?对此的任何见解将不胜感激。谢谢!
<details>
<summary>英文:</summary>
In `Java`, the following code:
long x = 123;
String s = "abc" + x;
takes a significantly more runtime than:
long x = 123;
String s = "abc" + String.valueOf(x);
I got to know this through leetcode. I was trying to solve the following problem: https://leetcode.com/problems/fraction-to-recurring-decimal/
Here is the exact code for my solution:
public String fractionToDecimal(int numerator, int denominator) {
long n = numerator, d = denominator;
boolean isNegative = (n * d < 0);
if(n < 0) n = -n;
if(d < 0) d = -d;
long q = n / d;
long r = n % d;
if(r == 0) return (isNegative ? "-" : "") + q;
StringBuilder sb = new StringBuilder();
if(isNegative) sb.append('-');
sb.append(q).append('.');
Map<Long, Integer> found = new HashMap<>();
int index = sb.length();
while(r > 0 && !found.containsKey(r)){
found.put(r, index++);
n = r * 10;
q = n / d;
r = n % d;
sb.append(q);
}
if(r > 0) {
sb.insert(found.get(r), "(");
sb.append(')');
}
return sb.toString();
}
When I click on `Submit` it takes as long as **7 milliseconds** to complete.
But if I literally just change line no. 8 from `+ q` to `+ String.valueOf(q)` the runtime plummets down to just **1 millisecond**. Please feel free to copy paste the code on leetcode to try it out there and see this change in runtime for yourself, if necessary.
This is highly confusing to me. Why is this happening? As per my understanding, in both the cases, compiler first converts the long to a String, and then concatenates those two Strings together, right? So, under the hood, isn't concatenating a String and a long exactly the same as concatenating two Strings together? Then why does one take more time to run than the other? Any insight would be highly appreciated. TIA.
</details>
# 答案1
**得分**: 7
`"abc" + 123` 是一个常量表达式 - 连接操作在*编译时*完成,因此最终在常量池中得到 "abc123"。
`"abc" + String.valueOf(123)` *不是*常量表达式。连接操作发生在执行时,这显然比仅使用编译时连接结果要昂贵得多。
因此,我预期结果与您在问题中实际报告的相反。
<details>
<summary>英文:</summary>
Note: this answer was written before the question was changed. It used to include the expressions shown below.
`"abc" + 123` is a constant expression - the concatenation is done at *compile-time* so "abc123" ends up in the constant pool.
`"abc" + String.valueOf(123)` is *not* a constant expression. The concatenation happens at execution time, which is obviously rather more expensive than just using the compile-time concatenation result.
So I'd expect the result to be the *opposite* of what you've actually reported in the question.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论