While-E
While-E

Reputation: 1555

Android/Java converting from int to String without allocations?

got thinking about having to repeatedly convert from int to String over the course of one of the apps I'm creating for Android. I sat down and wrote a little utility class that I think would alleviate the allocation of lurking variables that you cannot see because of function calls like Integer.toString(), and etc...

private int[] iMods = {
        1,
        10,
        100,
        1000,
        10000,
        100000,
        1000000,
        10000000,
        100000000,
        1000000000};

private int tmpInt = 0;
private int MAX_DIGITS = 6;
private char[] cScoreDigit = new char[MAX_DIGITS];
private int[] iScoreDigit = new int[MAX_DIGITS];
private StringBuilder mScoreStringBuilder = new StringBuilder("000000");


public String intToString(final int pInt, final int pMAX_DIGITS){
    MAX_DIGITS = pMAX_DIGITS;

    for (tmpInt = 1; tmpInt <= MAX_DIGITS; tmpInt++){   // Set each cScoreDigit to proper equivalent of iScoreDigit without cast!
        switch ((pInt % iMods[tmpInt]) / iMods[tmpInt - 1]){
        case 0:
            cScoreDigit[MAX_DIGITS - tmpInt] = '0';
            break;
        case 1:
            cScoreDigit[MAX_DIGITS - tmpInt] = '1';
            break;
        case 2:
            cScoreDigit[MAX_DIGITS - tmpInt] = '2';
            break;
        case 3:
            cScoreDigit[MAX_DIGITS - tmpInt] = '3';
            break;
        case 4:
            cScoreDigit[MAX_DIGITS - tmpInt] = '4';
            break;
        case 5:
            cScoreDigit[MAX_DIGITS - tmpInt] = '5';
            break;
        case 6:
            cScoreDigit[MAX_DIGITS - tmpInt] = '6';
            break;
        case 7:
            cScoreDigit[MAX_DIGITS - tmpInt] = '7';
            break;
        case 8:
            cScoreDigit[MAX_DIGITS - tmpInt] = '8';
            break;
        case 9:
            cScoreDigit[MAX_DIGITS - tmpInt] = '9';
        }       
    }

    // Delete all 0's
    mScoreStringBuilder.delete(0, mScoreStringBuilder.length());
    return mScoreStringBuilder.append(cScoreDigit).toString();
}

Now I'm just curious as to A) whether this is actually the correct way to do something like this, and B) whether something like this is worth looking into because of the extra math taking place on each step? Seems counter productive, but would at least restrain the GC from running correct? Thanks in advance!

[EDIT]

It's been brought to my attention that the StringBuilder.toString() will actually allocate a temporary object, which is what I was trying to avoid. Any other way to simply convert from char[] to String without having an allocation? Or like stated below is this just not possible with String class?

Upvotes: 3

Views: 1184

Answers (1)

Bill K
Bill K

Reputation: 62789

No, the toString at the end creates a new String (Check the code if you like, java library sources are all available).

Since strings are immutable, there is really no way to avoid allocation because you return a string.

If you return the string builder you used to build your number in and reused it the next time you were called and NEVER converted it to a string you'd be fine, but the second you convert it to a string (no matter how you did it) you are allocating memory.

To do this your method would either have to accept a passed-in mutable object (StringBuilder or char array) or it would have to reuse a static one (making it single threaded)

I tried this once and it always comes down to converting it to a string at some point undoing all your work and making it even slower than it would have been if you'd just used the obvious way.

Also remember that in Java short-term memory allocations aren't as bad as you'd think--they are more like stack allocations in C in terms of performance.

The research and testing I did indicated that the one thing you can do is avoid concatenating strings in a loop--everything else (including one-time string concatenations) the simplest code will be just as fast or faster than anything you can come up with.

Upvotes: 2

Related Questions