String to int OR int to String: which is faster?

I need to compare String (which is a valid integer) with an int value.

For String str, int integermy options are:

  • Integer.parseInt(str) == integer

  • str.equals(Integer.toString(integer))

Which one is faster and is there a better way?

Below is the support for EqualsIntString atlaste answer

 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;
}
+4
source share
4 answers

Only one way to find out: measure.

The quick JMH test shows that it is Integer.parseIntfaster, regardless of the size of the integer. But we are talking about 10 nanoseconds or so, and this is unlikely to make a big difference at your application level.

100% , , , (. parseManual equalsIntString ). , , ( , parseManual , , , equalsIntString ).

, .

( : - ) - (n) - , . , .

Benchmark                                       (n)  Mode  Samples   Score   Error  Units
c.a.p.SO30507506.manual                           1  avgt       10   6.579 ± 0.131  ns/op
c.a.p.SO30507506.manual                       12345  avgt       10  10.017 ± 0.401  ns/op
c.a.p.SO30507506.manual                   123456789  avgt       10  12.490 ± 0.243  ns/op
c.a.p.SO30507506.manualAtlaste                    1  avgt       10   7.914 ± 0.144  ns/op
c.a.p.SO30507506.manualAtlaste                12345  avgt       10  15.902 ± 0.593  ns/op
c.a.p.SO30507506.manualAtlaste            123456789  avgt       10  28.117 ± 0.463  ns/op
c.a.p.SO30507506.parse                            1  avgt       10   8.495 ± 0.325  ns/op
c.a.p.SO30507506.parse                        12345  avgt       10  21.614 ± 0.564  ns/op
c.a.p.SO30507506.parse                    123456789  avgt       10  34.692 ± 0.572  ns/op
c.a.p.SO30507506.stringEquals                     1  avgt       10  21.597 ± 0.594  ns/op
c.a.p.SO30507506.stringEquals                 12345  avgt       10  36.948 ± 1.144  ns/op
c.a.p.SO30507506.stringEquals             123456789  avgt       10  44.444 ± 1.011  ns/op

c.a.p.SO30507506.manual_unequal                   1  avgt       10   7.011 ± 0.149  ns/op
c.a.p.SO30507506.manual_unequal               12345  avgt       10  10.244 ± 0.350  ns/op
c.a.p.SO30507506.manual_unequal           123456789  avgt       10  13.135 ± 0.797  ns/op
c.a.p.SO30507506.manualAtlaste_unequal            1  avgt       10   4.328 ± 0.111  ns/op
c.a.p.SO30507506.manualAtlaste_unequal        12345  avgt       10   4.359 ± 0.115  ns/op
c.a.p.SO30507506.manualAtlaste_unequal    123456789  avgt       10   4.339 ± 0.103  ns/op
c.a.p.SO30507506.parse_unequal                    1  avgt       10   8.304 ± 0.251  ns/op
c.a.p.SO30507506.parse_unequal                12345  avgt       10  21.514 ± 0.405  ns/op
c.a.p.SO30507506.parse_unequal            123456789  avgt       10  35.257 ± 1.043  ns/op
c.a.p.SO30507506.stringEquals_unequal             1  avgt       10  19.060 ± 0.162  ns/op
c.a.p.SO30507506.stringEquals_unequal         12345  avgt       10  31.829 ± 0.427  ns/op
c.a.p.SO30507506.stringEquals_unequal     123456789  avgt       10  41.870 ± 0.252  ns/op

:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
public class SO30507506 {

  @Param({"1", "12345", "123456789"}) int n;
  int i;
  String s;

  @Setup public void setup() {
    i = n;
    s = String.valueOf(n);
  }

  @Benchmark public boolean parse() {
    return Integer.parseInt(s) == i;
  }

  @Benchmark public boolean stringEquals() {
    return s.equals(Integer.toString(i));
  }

  @Benchmark public boolean manual() {
    return parseManual(s) == i;
  }

  @Benchmark public boolean manualAtlaste() {
    return equalsIntString(i, s);
  }

  @Benchmark public boolean parse_unequal() {
    return Integer.parseInt(s) == i * 2;
  }

  @Benchmark public boolean stringEquals_unequal() {
    return s.equals(Integer.toString(i * 2));
  }

  @Benchmark public boolean manual_unequal() {
    return parseManual(s) == i * 2;
  }

  @Benchmark public boolean manualAtlaste_unequal() {
    return equalsIntString(i * 2, s);
  }

  private static int parseManual(String s) {
    int result = 0;
    int sign = s.charAt(0) == '-' ? -1 : 1;
    int startIndex = (s.charAt(0) >= '0' && s.charAt(0) <= '9') ? 0 : 1;
    for (int i = startIndex; i < s.length(); i++) {
      result *= 10;
      result += s.charAt(i) - '0';
    }
    return result * sign;
  }

  private static boolean equalsIntString(int value, String s) {
    if (s.isEmpty()) return false; // This is never good.
    if ((s.charAt(0) == '-' && value >= 0) || (s.charAt(0) != '-' && value < 0)) return false; // positive/negative check

    // Define the limit. This is basically the end of the string to check.
    int limit = 0;
    if (value < 0) {
      limit = 1;
      value = -value;
    }

    for (int i = s.length() - 1; i >= limit; --i) {
      char expected = (char) ('0' + (value % 10)); // the modulo will be optimized by the JIT because 10 is a constant
      value /= 10; // same story.

      if (s.charAt(i) != expected) return false;
    }
    return true;
  }
}
+4

. , , Java , . .

: loadstring, . , .

10- (, ) . , Integer.tryParse. , div/mul . , , "-". , .

:

  • ( !!!). =
  • fail/pass , ( ) .
  • .
  • .

, . , / , , , ... - , .

, , . Java , #:-) , ...

public int ConvertStringToInt(string s)
{
    int val = 0;
    if (s[0] == '-') // 1
    {
        for (int i = 1; i < s.Length; ++i )
        {
            if (s[i] >= '0' && s[i] <= '9') // 2
            {
                throw new Exception();
            }
            val = val * 10 + s[i] - '0';
        }
        return -val;
    }
    else
    {
        for (int i = 0; i < s.Length; ++i)
        {
            if (s[i] >= '0' && s[i] <= '9')
            {
                throw new Exception();
            }
            val = val * 10 + s[i] - '0';
        }
        return val;
    }
}

, , , , 1. , , ( ), 2. , , , , , 2. :

public int ConvertStringToInt(string s)
{
    int val = 0;
    if (s[0] == '-')
    {
        for (int i = 1; i < s.Length; ++i )
        {
            val = val * 10 + s[i] - '0';
        }
        return -val;
    }
    else
    {
        for (int i = 0; i < s.Length; ++i)
        {
            val = val * 10 + s[i] - '0';
        }
        return val;
    }
}

, . , ? , , . , , , "-" char, . :

public bool EqualsStringInt(string s, int value)
{
    int val = 0;
    if (s[0] == '-')
    {
        if (value >= 0) { return false; } // otherwise we expected another char

        for (int i = 1; i < s.Length; ++i )
        {
            val = val * 10 + s[i] - '0'; // s[i] must be a char between '0'-'9' as implied by the question.
        }
        return (-val) == value;
    }
    else
    {
        if (value < 0) { return false; } // otherwise we expected another char

        for (int i = 0; i < s.Length; ++i)
        {
            val = val * 10 + s[i] - '0';
        }
        return val == value;
    }
}

++, : ++: std::string . , , .

, . , :

  • . . , GC / !
  • . , . GC, .

, .

, , . , :

  • ,
  • ,
  • , .

, :

public bool EqualsIntString(int value, string s)
{
    if (s.Length == 0) { return false; } // This is never good.
    if ((s[0] == '-' && value >= 0) || (s[0] != '-' && value < 0)) { return false; } // positive/negative check

    // Define the limit. This is basically the end of the string to check.
    int limit = 0;
    if (value < 0) // 1
    {
        limit = 1;
        value = -value;
    }

    for (int i=s.Length-1; i>=limit; --i)
    {
        char expected = (char)('0' + (value % 10)); // the modulo will be optimized by the JIT because 10 is a constant
        value /= 10; // same story.

        if (s[i] != expected) { return false; }
    }
    return true;
}

, , . 1.

? ... ++ . .

10log . . . , 10log , , !

. , , , .

, , .

+1

,

Integer.parseInt(str) == integer

. , , , Integer.toString - .

, , Integer.toString, .

, .

OTOH, Integer.parseInt Unicode-, 0 9, . , Guava Ints.parseInt .


, NumberFormatException. , , Integer.toString .

0

Interger.Parse(), , , .., ...

- .

-1

All Articles