Parse a URI String into Name-Value Collection

前端 未结 19 2469
难免孤独
难免孤独 2020-11-22 01:34

I\'ve got the URI like this:

https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_         


        
19条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-22 02:12

    Here is my solution with reduce and Optional:

    private Optional> splitKeyValue(String text) {
        String[] v = text.split("=");
        if (v.length == 1 || v.length == 2) {
            String key = URLDecoder.decode(v[0], StandardCharsets.UTF_8);
            String value = v.length == 2 ? URLDecoder.decode(v[1], StandardCharsets.UTF_8) : null;
            return Optional.of(new SimpleImmutableEntry(key, value));
        } else
            return Optional.empty();
    }
    
    private HashMap parseQuery(URI uri) {
        HashMap params = Arrays.stream(uri.getQuery()
                .split("&"))
                .map(this::splitKeyValue)
                .filter(Optional::isPresent)
                .map(Optional::get)
                .reduce(
                    // initial value
                    new HashMap(), 
                    // accumulator
                    (map, kv) -> {
                         map.put(kv.getKey(), kv.getValue()); 
                         return map;
                    }, 
                    // combiner
                    (a, b) -> {
                         a.putAll(b); 
                         return a;
                    });
        return params;
    }
    
    • I ignore duplicate parameters (I take the last one).
    • I use Optional> to ignore garbage later
    • The reduction start with an empty map, then populate it on each SimpleImmutableEntry

    In case you ask, reduce requires this weird combiner in the last parameter, which is only used in parallel streams. Its goal is to merge two intermediate results (here HashMap).

提交回复
热议问题