Interleave data using Java

Posted on

Problem

protected static String[] applyInterleave(String interleave, int lengthOfSequence, int numOfPermutations){
    String[] interleavedPatterns = new String[numOfPermutations];
    char[] pattern = interleave.toCharArray();
    StringBuilder interleavedPattern = new StringBuilder("");

    for(int i = 0; i < numOfPermutations; i++){
        char[] data = designs[i].toCharArray();
        for(int j = 0; j < lengthOfSequence; j++)
            interleavedPattern.append(data[Character.getNumericValue(pattern[j])-1]);

        interleavedPatterns[i] = interleavedPattern.toString();
        interleavedPattern = new StringBuilder("");
    }
    return interleavedPatterns;
}

In this code, design is of size numOfPermutations and each element in design is a string of length lengthOfSequence. Now, I am taking each element in design and applying an interleave mapping based on the parameter interleave.

For instance, let’s say the string is 1432. Then, I take each element in design and I reorder it so that the 1st char of string is still the 1st, then the 4th char becomes the 2nd, the 3rd char stays the 3rd, and the 2nd char becomes the 4th.

For example, if the first element in design, design[0] = 4321 and if the passed in parameter for interleave is 1432 then 4321 is reordered as 4123. There are very specific reasons why I am only working with String instead of int, so I am not interested in changing the variable types.

Now, if my design array is really large, say 362880 indices long, then this method takes quite a while. I have optimized to the best of my ability, but is there a way to speed this up even more?

Solution

Optimization 1

Instead of constantly doing Character.getNumericValue(pattern[j])-1 in the inner loop, you could create a precomputed integer array to hold those values. That way, you could replace that expression with patIndex[j].

Optimization 2

Instead of using multiple instances of StringBuilder, you could use and reuse a single char array and create strings from that.

Optimization 3

Instead of creating a char array from your designs[i] string, you could just leave designs[i] as a string and use String.charAt() to read each character.

Sample rewrite

Using the above 3 optimizations, I arrived at:

static String[] applyInterleave(String interleave, int lengthOfSequence,
        int numOfPermutations)
{
    String[] interleavedPatterns = new String[numOfPermutations];
    char  [] pattern  = interleave.toCharArray();
    int   [] patIndex = new int[lengthOfSequence];

    for (int i = 0; i < lengthOfSequence; i++) {
        patIndex[i] = Character.getNumericValue(pattern[i])-1;
    }

    for(int i = 0; i < numOfPermutations; i++) {
        String s = designs[i];
        for(int j = 0; j < lengthOfSequence; j++) {
            pattern[j] = s.charAt(patIndex[j]);
        }
        interleavedPatterns[i] = new String(pattern);
    }
    return interleavedPatterns;
}

I tested this against the original function and found that it was approximately 3x faster.

Leave a Reply

Your email address will not be published. Required fields are marked *