I have a pipe delimited file which I parse to get system options. The environment is sensitive to heap allocation and we are trying to avoid garbage collection.
Below is the code I am using to parse the pipe delimited string. This function is called about 35000 times. I was wondering if there was a better approach that doesn't create as much memory churn.
static int countFields(String s) {
    int n = 1;
    for (int i = 0; i < s.length(); i++)
        if (s.charAt(i) == '|')
            n++;
    return n;
}
static String[] splitFields(String s) {
    String[] l = new String[countFields(s)];
    for (int pos = 0, i = 0; i < l.length; i++) {
        int end = s.indexOf('|', pos);
        if (end == -1)
            end = s.length();
        l[i] = s.substring(pos, end);
        pos = end + 1;
    }
    return l;
}
EDIT 1, about java version:
For business reasons we are stuck at JDK 1.6.0_25.
EDIT 2 about String and String[] usage:
The String[] is used to perform the system setup logic. Basically, if String[0].equals("true") then enable debugging. That's the usage pattern
EDIT 3 about garbage collected objects:
The input String and the String[] are eventually GC'd. The input String is a single line from system setup file which is GC'd after the entire file is processed and the String[] is GC'd after the entire line has been processed.
EDIT - SOLUTION:
This is a combo of Peter Lawrey and zapl's solutions. Also, this class is NOT thread safe.
public class DelimitedString {
    private static final Field EMPTY = new Field("");
    private char delimiter = '|';
    private String line = null;
    private Field field = new Field();
    public DelimitedString() { }
    public DelimitedString(char delimiter) {
        this.delimiter = delimiter;
    }
    public void set(String line) {
        this.line = line;
    }
    public int length() {
        int numberOfFields = 0;
        if (line == null)
            return numberOfFields;
        int idx = line.indexOf(delimiter);
        while (idx >= 0) {
            numberOfFields++;
            idx = line.indexOf(delimiter, idx + 1);
        }
        return ++numberOfFields;
    }
    public Field get(int fieldIndex) {
        if (line == null)
            return EMPTY;
        int currentField = 0;
        int startIndex = 0;
        while (currentField < fieldIndex) {
            startIndex = line.indexOf(delimiter, startIndex);
            // not enough fields
            if (startIndex < 0)
                return EMPTY;
            startIndex++;
            currentField++;
        }
        int endIndex = line.indexOf(delimiter, startIndex);
        if (endIndex == -1)
            endIndex = line.length();
        fieldLength = endIndex - startIndex;
        if (fieldLength == 0)
            return EMPTY;
        // Populate field
        for (int i = 0; i < fieldLength; i++) {
            char c = line.charAt(startIndex + i);
            field.bytes[i] = (byte) c;
        }
        field.fieldLength = fieldLength;
        return field;
    }
    @Override
    public String toString() {
        return new String(line + " current field = " + field.toString());
    }
    public static class Field {
        // Max size of a field
        private static final int DEFAULT_SIZE = 1024;
        private byte[] bytes = null;
        private int fieldLength = Integer.MIN_VALUE;
        public Field() {
            bytes = new byte[DEFAULT_SIZE];
            fieldLength = Integer.MIN_VALUE;
        }
        public Field(byte[] bytes) {
            set(bytes);
        }
        public Field(String str) {
            set(str.getBytes());
        }
        public void set(byte[] str) {
            int len = str.length;
            bytes = new byte[len];
            for (int i = 0; i < len; i++) {
                byte b = str[i];
                bytes[i] = b;
            }
            fieldLength = len;
        }
        public char charAt(int i) {
            return (char) bytes[i];
        }
        public byte[] getBytes() {
            return bytes;
        }
        public int length() {
            return fieldLength;
        }
        public short getShort() {
            return (short) readLong();
        }
        public int getInt() {
            return (int) readLong();
        }
        public long getLong() {
            return readLong();
        }
        @Override
        public String toString() {
            return (new String(bytes, 0, fieldLength));
        }
        // Code taken from Java class Long method parseLong()
        public long readLong() {
            int radix = 10;
            long result = 0;
            boolean negative = false;
            int i = 0, len = fieldLength;
            long limit = -Long.MAX_VALUE;
            long multmin;
            int digit;
            if (len > 0) {
                char firstChar = (char) bytes[0];
                if (firstChar < '0') { // Possible leading "-"
                    if (firstChar == '-') {
                        negative = true;
                        limit = Long.MIN_VALUE;
                    } else
                        throw new NumberFormatException("Invalid leading character.");
                    if (len == 1) // Cannot have lone "-"
                        throw new NumberFormatException("Negative sign without trailing digits.");
                    i++;
                }
                multmin = limit / radix;
                while (i < len) {
                    // Accumulating negatively avoids surprises near MAX_VALUE
                    digit = Character.digit(bytes[i++], radix);
                    if (digit < 0)
                        throw new NumberFormatException("Single digit is less than zero.");
                    if (result < multmin)
                        throw new NumberFormatException("Result is less than limit.");
                    result *= radix;
                    if (result < limit + digit)
                        throw new NumberFormatException("Result is less than limit plus new digit.");
                    result -= digit;
                }
            } else {
                throw new NumberFormatException("Called readLong with a length <= 0. len=" + len);
            }
            return negative ? result : -result;
        }
    }
}
 
     
     
     
     
     
     
     
    