Splitting URL query string to key-value pairs
To decode the query string correctly, you must take care of percent-encoding, like %25 for a literal percent, or %C3%A4 for an ä (encoded as UTF-8). The canonical code for doing this is:

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Map;

public class QueryStringDecoder {

    public static Map&lt;String, String&gt; decodeQueryString(String query) {
        try {
            Map&lt;String, String&gt; params = new LinkedHashMap&lt;&gt;();
            for (String param : query.split("&amp;")) {
                String[] keyValue = param.split("=", 2);
                String key = URLDecoder.decode(keyValue[0], "UTF-8");
                String value = keyValue.length &gt; 1 ? URLDecoder.decode(keyValue[1], "UTF-8") : "";
                if (!key.isEmpty()) {
                    params.put(key, value);
                }
            }
            return params;
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e); // Cannot happen with UTF-8 encoding.
        }
    }

    public static void main(String[] args) {
        System.out.println(decodeQueryString("&amp;&amp;&amp;"));
        System.out.println(decodeQueryString("&amp;&amp;&amp;a=b"));
        System.out.println(decodeQueryString("a=b&amp;c=%26%25==&amp;utf8=%E2%9C%93"));
        System.out.println(decodeQueryString("latin1=%FC"));
    }
}


I don't know why you prefer to do the parsing in a single pass. That would be possible, but the single-pass code must then behave exactly like the above code.
Furthermore, since this part of the code is probably not the bottleneck, there is no point in optimizing it for execution speed instead of readability.