Split a string into a list of tokens
tmp is never a good name for a variable.  In this case, you should call it token instead, or perhaps word.  And you rightly complain that building strings using repeated += operations is inefficient, and correctly suggest that .substring() would be better.

Logically, then, you need to find the starting and ending indexes of each token!  So, let's define those helper functions (as private static functions):

/**
 * Considering str starting at startIndex, find the index at which the 
 * next token starts.
 *
 * @return The index of the start of a token (or str.length() if no more
 *         tokens).
 */
private static int start(String str, char sep, int startIndex) {
    int i;
    for (i = startIndex; i &lt; str.length() &amp;&amp; str.charAt(i) == sep; i++);
    return i;
}

/**
 * Considering str starting at startIndex, find the index at which the 
 * current token ends.
 *
 * @return The index just beyond the end of a token (the index of a
 *         sep character, or str.length() if this is the last token)
 */
private static int end(String str, char sep, int startIndex) {
    assert(str.charAt(sep) != sep);
    int i;
    for (i = startIndex; i &lt; str.length() &amp;&amp; str.charAt(i) != sep; i++);
    return i;
}


Then, we can use them in tokenize():

public static String[] tokenize(String str, char sep) {
    int tokenCount = 0;
    for (int s, e = 0; (s = start(str, sep, e)) &lt; str.length(); e = end(str, sep, s)) {
        tokenCount++;
    }
    String[] tokens = new String[tokenCount];
    tokenCount = 0;
    for (int s, e = 0; (s = start(str, sep, e)) &lt; str.length(); ) {
        tokens[tokenCount++] = str.substring(s, e = end(str, sep, s));
    }
    assert(tokens.length == tokenCount);
    return tokens;
}


Notice that now you can take advantage of the helper functions to predetermine the size of the array.  Also, a lot of the repetitiveness of your conditions and loops is eliminated.

All of the analysis is done using string indexes, so there is no string manipulation other than just the essential .substring() calls — and even the trim() call is gone!