我需要将 String(这是一个有效的整数)与 int 值进行比较。
对于String str, int integer,我的选择是:
Integer.parseInt(str) == integer
str.equals(Integer.toString(integer))
哪一种更快,有没有更好的方法?
以下受到 atlaste 答案的 EqualsIntString 的启发
private static boolean checkEquality(final String string, final long value) {
if (string == null) {
return false;
}
final int length = string.length();
if (length == 0) {
return false;
}
long absValue;
final byte minIndex;
if (string.charAt(0) == '-') {
if (value > 0) {
return false;
}
absValue = -value;
minIndex = 1;
} else {
if (value < 0) {
return false;
}
absValue = value;
if (string.charAt(0) == '+') {
minIndex = 1;
} else {
minIndex = 0;
}
}
for (int idx = length - 1; idx >= minIndex; idx--) {
final byte rem = (byte) (absValue % 10);
absValue /= 10;
final int diff = string.charAt(idx) - rem - 48;
if (diff != 0) {
return false;
}
}
return absValue == 0;
}
Run Code Online (Sandbox Code Playgroud)
只有一种方法可以知道:测量。
\n\n快速 JMH 基准测试表明Integer.parseInt,无论整数的大小如何,速度都会更快。但我们谈论的是 10 纳秒左右,它不太可能在您的应用程序级别产生太大差异。
如果你100%确定你的字符串是一个有效的整数,你也可以手动解析它,这会更快(参见下面代码中的parseManual和方法)。equalsIntString使用哪种方法还取决于您期望这些值经常相等还是经常不同(如果它们经常相等,则parseManual效果更好,如果您期望它们平均不同,equalsIntString则速度更快)。
因此,数据集的特征在决策中也很重要。
\n\n完整结果(分数以每次操作的纳秒为单位:越小越好) -(n)列是要比较的整数。第一部分比较相等的值,第二部分比较不相等的值。
Benchmark (n) Mode Samples Score Error Units\nc.a.p.SO30507506.manual 1 avgt 10 6.579 \xc2\xb1 0.131 ns/op\nc.a.p.SO30507506.manual 12345 avgt 10 10.017 \xc2\xb1 0.401 ns/op\nc.a.p.SO30507506.manual 123456789 avgt 10 12.490 \xc2\xb1 0.243 ns/op\nc.a.p.SO30507506.manualAtlaste 1 avgt 10 7.914 \xc2\xb1 0.144 ns/op\nc.a.p.SO30507506.manualAtlaste 12345 avgt 10 15.902 \xc2\xb1 0.593 ns/op\nc.a.p.SO30507506.manualAtlaste 123456789 avgt 10 28.117 \xc2\xb1 0.463 ns/op\nc.a.p.SO30507506.parse 1 avgt 10 8.495 \xc2\xb1 0.325 ns/op\nc.a.p.SO30507506.parse 12345 avgt 10 21.614 \xc2\xb1 0.564 ns/op\nc.a.p.SO30507506.parse 123456789 avgt 10 34.692 \xc2\xb1 0.572 ns/op\nc.a.p.SO30507506.stringEquals 1 avgt 10 21.597 \xc2\xb1 0.594 ns/op\nc.a.p.SO30507506.stringEquals 12345 avgt 10 36.948 \xc2\xb1 1.144 ns/op\nc.a.p.SO30507506.stringEquals 123456789 avgt 10 44.444 \xc2\xb1 1.011 ns/op\n\nc.a.p.SO30507506.manual_unequal 1 avgt 10 7.011 \xc2\xb1 0.149 ns/op\nc.a.p.SO30507506.manual_unequal 12345 avgt 10 10.244 \xc2\xb1 0.350 ns/op\nc.a.p.SO30507506.manual_unequal 123456789 avgt 10 13.135 \xc2\xb1 0.797 ns/op\nc.a.p.SO30507506.manualAtlaste_unequal 1 avgt 10 4.328 \xc2\xb1 0.111 ns/op\nc.a.p.SO30507506.manualAtlaste_unequal 12345 avgt 10 4.359 \xc2\xb1 0.115 ns/op\nc.a.p.SO30507506.manualAtlaste_unequal 123456789 avgt 10 4.339 \xc2\xb1 0.103 ns/op\nc.a.p.SO30507506.parse_unequal 1 avgt 10 8.304 \xc2\xb1 0.251 ns/op\nc.a.p.SO30507506.parse_unequal 12345 avgt 10 21.514 \xc2\xb1 0.405 ns/op\nc.a.p.SO30507506.parse_unequal 123456789 avgt 10 35.257 \xc2\xb1 1.043 ns/op\nc.a.p.SO30507506.stringEquals_unequal 1 avgt 10 19.060 \xc2\xb1 0.162 ns/op\nc.a.p.SO30507506.stringEquals_unequal 12345 avgt 10 31.829 \xc2\xb1 0.427 ns/op\nc.a.p.SO30507506.stringEquals_unequal 123456789 avgt 10 41.870 \xc2\xb1 0.252 ns/op\nRun Code Online (Sandbox Code Playgroud)\n\n代码:
\n\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.AverageTime)\npublic class SO30507506 {\n\n @Param({"1", "12345", "123456789"}) int n;\n int i;\n String s;\n\n @Setup public void setup() {\n i = n;\n s = String.valueOf(n);\n }\n\n @Benchmark public boolean parse() {\n return Integer.parseInt(s) == i;\n }\n\n @Benchmark public boolean stringEquals() {\n return s.equals(Integer.toString(i));\n }\n\n @Benchmark public boolean manual() {\n return parseManual(s) == i;\n }\n\n @Benchmark public boolean manualAtlaste() {\n return equalsIntString(i, s);\n }\n\n @Benchmark public boolean parse_unequal() {\n return Integer.parseInt(s) == i * 2;\n }\n\n @Benchmark public boolean stringEquals_unequal() {\n return s.equals(Integer.toString(i * 2));\n }\n\n @Benchmark public boolean manual_unequal() {\n return parseManual(s) == i * 2;\n }\n\n @Benchmark public boolean manualAtlaste_unequal() {\n return equalsIntString(i * 2, s);\n }\n\n private static int parseManual(String s) {\n int result = 0;\n int sign = s.charAt(0) == \'-\' ? -1 : 1;\n int startIndex = (s.charAt(0) >= \'0\' && s.charAt(0) <= \'9\') ? 0 : 1;\n for (int i = startIndex; i < s.length(); i++) {\n result *= 10;\n result += s.charAt(i) - \'0\';\n }\n return result * sign;\n }\n\n private static boolean equalsIntString(int value, String s) {\n if (s.isEmpty()) return false; // This is never good.\n if ((s.charAt(0) == \'-\' && value >= 0) || (s.charAt(0) != \'-\' && value < 0)) return false; // positive/negative check\n\n // Define the limit. This is basically the end of the string to check.\n int limit = 0;\n if (value < 0) {\n limit = 1;\n value = -value;\n }\n\n for (int i = s.length() - 1; i >= limit; --i) {\n char expected = (char) (\'0\' + (value % 10)); // the modulo will be optimized by the JIT because 10 is a constant\n value /= 10; // same story.\n\n if (s.charAt(i) != expected) return false;\n }\n return true;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1223 次 |
| 最近记录: |