Splitting URL query string to key-value pairs I have a URL query string "key={value}&amp;key2={value2}&amp;key3={value3}" and have to produce a key-value pair of the string by splitting &amp; and =. Also, I have to watch out for corner cases such that if a key isn't present do not add it to the hash map but if a value is missing the key can be added with an empty value. One way is to first split the string by &amp; and finally by =. So this can be accomplished but having two passes. But I am attempting to accomplish this in one pass.

First idea: I came up with one pass using the split function, but it didn't account for corner cases.

public Map&lt;String, String&gt; splitString(String s) {
    // String s represents ParamAndMacro
    String[] split = s.split("=|\\&amp;");
    int length = split.length;
    Map&lt;String, String&gt; maps = new HashMap&lt;&gt;();
    for (int i=0; i&lt;length; i+=2){
          maps.put(split[i], split[i+1]);
     } 
    return maps;
}


Second idea: One pass with certain conditions and using StringBuilder:

public Map&lt;String, String&gt; splitString(String s){
 Map&lt;String, String&gt; maps = new HashMap&lt;&gt;();
 int length = s.length();
 StringBuilder sb = new StringBuilder();
 String key = "";
 String value = "";

char prev = ' ';
for (int i=0; i&lt;length; i++) {
    char a = s.charAt(i);
    if ( a != '=' &amp;&amp; a != '&amp;' &amp;&amp; prev != a) {
           sb.append(a);        
      }
    //finds a key
    else if( a == '=' &amp;&amp; prev != a &amp;&amp; prev != '&amp;') {
          key = sb.toString();
          sb = new StringBuilder();
      }
    // finds a value and also ensuring a key is not empty
    else if (a=='&amp;' &amp;&amp; prev != a &amp;&amp; prev != '=') {
          value = sb.toString();
          sb = new StringBuilder();
          maps.put(key, value);
            }
    // checks corner case to see if a value is empty
    else if (prev=='=' &amp;&amp; a == '&amp;') {
          value = "";
          maps.put(key, value);
          sb = new StringBuilder();
    }
   //how to check if a key is missing and skip to other pair

            prev = a;
    }
    return maps;
}


My concern is whether my code is efficient in terms of splitting and using StringBuilder. Please feel free to improve or give suggestions.
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.