views:

557

answers:

5

Just wondering if anyone knew off the top of their heads if there was much difference in doing the following:

String wibble = "<blah> blah blah </blah>.... <wibble> blah wibble blah </wibble> some more test here";

int i = wibble.lastIndexOf(">");
int j = wibble.lastIndexOf('>');
+3  A: 

Performance-wise, there might be a slight difference. For searching a single character, it's faster or equal to use char instead of String.

Mehrdad Afshari
A: 

A string has extra overhead that is required no matter what it's length (unless you have a really smart compiler that will optimise single character string literals into character constants anyway :)), so you should prefer the char version if you are only searching for single characters. It's not an evil optimisation as it is readably equivalent either way.

workmad3
+4  A: 

You can actually look into the source code of String class. It seems lastIndex(char) and lastIndex(String) were actually written separately. There should also be an overhead with String class. So char version might be a little bit faster, but I doubt there will be a case with any significant performance difference.

http://www.docjar.com/html/api/java/lang/String.java.html

dasony
+1 to just reading the code!
SCdF
+2  A: 

Where there's no difference in readability (as in this case) it's better to go with the version which only searches for a char. There's less work for lastIndexOf to do - it's easier to find a single element in a list than to find a sublist (which is effectively what searching for a string will do).

Jon Skeet
Readability being the key here. An unacceptable micro-opt in my opinion would be `if (needle.length() == 1) { i = haystack.lastIndexOf(needle.charAt[0]); } else {...`
Mark Peters
there might be an (admittedly weak) argument for using the string version for maintainability if the search string might be more than one character long in the future--i.e. it's less effort to go from `">"` to `"/>"`, if a change like that is needed.
Kip
@Kip: That's easy enough to change when you need it, IMO.
Jon Skeet
+9  A: 

Opinions are great but data are better. I wrote a quick benchmark:

Test Code

public static void main(String[] args)
{
  System.out.println("Starting perfo test");

  final long NUM_TESTS = 100000000L;

  String wibble = "<blah> blah blah </blah>.... <wibble>"
                + " blah wibble blah </wibble> some more test here";
  int x = -1;
  Stopwatch sw = new Stopwatch();

  System.out.println("--perfo test with " + NUM_TESTS + " iterations--");

  sw.start();
  for(long i = 0; i < NUM_TESTS; i++)
    x = wibble.lastIndexOf(">");
  sw.stop();
  System.out.println("String first pass: " + sw + " seconds");

  sw.start();
  for(long i = 0; i < NUM_TESTS; i++)
    x = wibble.lastIndexOf('>');
  sw.stop();
  System.out.println("Char first pass: " + sw + " seconds");

  sw.start();
  for(long i = 0; i < NUM_TESTS; i++)
    x = wibble.lastIndexOf('>');
  sw.stop();
  System.out.println("Char second pass: " + sw + " seconds");

  sw.start();
  for(long i = 0; i < NUM_TESTS; i++)
    x = wibble.lastIndexOf(">");
  sw.stop();
  System.out.println("String second pass: " + sw + " seconds");

  //Compiler warning said x was never read locally.. this is to
  //ensure the compiler doesn't optimize "x" away..
  System.out.println(x); 
}

Output

Starting perfo test
--perfo test with 100000000 iterations--
String first pass: 8.750 seconds
Char first pass: 6.500 seconds
Char second pass: 6.437 seconds
String second pass: 8.610 seconds
63

Conclusion

The version with a char is about 25% faster, but both versions execute very quickly so it probably won't ever be a bottleneck in your code.

Kip