String 到 int 或 int 到 String:哪个更快?

lab*_*jee 5 java performance

我需要将 String(这是一个有效的整数)与 int 值进行比较。

对于String str, int integer,我的选择是:

  1. Integer.parseInt(str) == integer

  2. 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)

ass*_*ias 5

只有一种方法可以知道:测量。

\n\n

快速 JMH 基准测试表明Integer.parseInt,无论整数的大小如何,速度都会更快。但我们谈论的是 10 纳秒左右,它不太可能在您的应用程序级别产生太大差异。

\n\n

如果你100%确定你的字符串是一个有效的整数,你也可以手动解析它,这会更快(参见下面代码中的parseManual和方法)。equalsIntString使用哪种方法还取决于您期望这些值经常相等还是经常不同(如果它们经常相等,则parseManual效果更好,如果您期望它们平均不同,equalsIntString则速度更快)。

\n\n

因此,数据集的特征在决策中也很重要。

\n\n

完整结果(分数以每次操作的纳秒为单位:越小越好) -(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\n
Run 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}\n
Run Code Online (Sandbox Code Playgroud)\n


Mar*_*lan -1

我会选择 Interger.Parse(),它在面对不同的本地化文化等时可能比其他方法更有弹性......

速度并不是真正的问题,有效的结果才是问题。