2

In Java (maybe the same for other langues as well) the charAt(x) method for accessing characters in a string is much slower than accessing the character elements in a char[]. This doesn't make much sense to me since String is using a char[] to represent the data.

Here is my test and results on this.

Testing charAt()

for(int i = 1000000; i >= 0; i--){
    char c = s.charAt(5);
}

charAt() elapsed time = 0.00261095

for(int i = 1000000; i >= 0; i--){
    char c = sArr[5];
}

arr[] elapsed time 0.001620297

From String.Java

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
Marquis Blount
  • 7,585
  • 8
  • 43
  • 67

4 Answers4

2

Offhand, I can think of at least a couple of reasons:

  1. charAt is a method call

  2. In Java 1.7.0_05 (thanks for the precise version, Holger) and below, within charAt, String does work to determine which entry in the underlying char[] to give you, since strings can share char[] arrays:

    if ((index < 0) || (index >= count)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index + offset];
    

    (offset is the offset in the shared char[].)

    In Java 1.7.0_06 and above, it still does a range check:

    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
    

So we can see that charAt does what you're doing (accessing a char[] entry), but also has to have the overhead of a method call and the range check (and in Java 7 and earlier, the index + offset calculation). It can't help but be a bit slower.

Then there's the possibility of measurement error, as naive micro-benchmarks in Java tend to be problematic.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

If you take a look at the source code of String, you will realise that once you call the method, two checks are being made on the provided index. Other than this, a method consumes some time by itself when called. These two combined are responsible for the time delay you noticed.

fill͡pant͡
  • 1,147
  • 2
  • 12
  • 24
1

The error check inside of the charAt() method is actually accounted for the difference. The test that I created wasn't “fair”, the char[x] test doesn't have error handling so the times were faster

//error check from charAt()

if ((index < 0) || (index >= value.length)) {
    throw new StringIndexOutOfBoundsException(index);
}

Updated arr[x] test with the following

    for(int i = 1000000; i >= 0; i--){
        if(dummy < 0 || dummy >= sArr.length) throw new IndexOutOfBoundsException();
        char c = sArr[5];
    }

updated time: arr[] elapsed time 0.002208887

A lot closer to charAt(i) now.

Holger
  • 285,553
  • 42
  • 434
  • 765
Marquis Blount
  • 7,585
  • 8
  • 43
  • 67
  • Whether instructions are received on a rising or falling portion of a pulse can also offset the usage of finding elapsed time. At least it's that way in C. – Feek Feb 07 '16 at 10:04
0

Because charAt() is a method and it needs to be placed on the runtime stack and control needs to be altered each time it is called, which takes a little bit of time. To the best of my knowledge they both perform the same operation.

Feek
  • 297
  • 3
  • 15