Aggregate List<String> into HashMap<String, T> using Stream API

北慕城南 提交于 2021-02-16 20:56:51

问题


I have a MultivaluedMap and a list of strings, and I would like to see which of those string are keys in the MultivaluedMap. For each of the strings that are keys in the MultivaluedMap, I want to construct a new Thing out of the value of that key, set that string as a new key in a new HashMap<String, Thing>, and set the new Thing I've created as the value for that new key in the HashMap.

Right now, using a vanilla forEach, I have the following working solution:

MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
HashMap<String, Thing> result = new HashMap<String, Thing>();

listOfStrings.forEach( (key) -> {
    String value = params.getFirst(key);
    if (value != null && !value.isEmpty()) {
        result.put(key, new Thing(value));
    }
});

However, I would like to implement a functional solution to this using the Java Stream API, and have attempted a fews solution. I have the following, which looks like it should work, but it does not:

MultivaluedMap<String, String> params = uriInfo.getQueryParameters();

HashMap<String, Thing> result = listOfStrings
        .stream()
        .filter(params::containsKey)
        .map( e -> new AbstractMap.SimpleEntry<String, Thing>(e, new Thing(params.getFirst(e))))
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

The Entry::getKey and Entry::getValue are giving a "Non-static method cannot be referred from a static context". I've tried other variations of this: constructing the objects in keyMapper and valueMapper lambdas, and using reduce with an empty map as the initial value. None have worked.

How would I rewrite my first, working solution using the Java Stream API and aggregation (e.g. collect, reduce)? I have referenced this post and this post and this post.


回答1:


Your code is fine. You just need to change the return type to Map instead of HashMap. If you need it to be HashMap specifically, you can pass HashMap::new into the factory overload.

One improvement I'd make is to cut out the unnecessary map() operation and do the lookup in the collector:

Map<String, Thing> result = listOfStrings
        .stream()
        .filter(params::containsKey)
        .collect(Collectors.toMap(Function.identity(), k -> new Thing(params.getFirst(k))));


来源:https://stackoverflow.com/questions/45826117/aggregate-liststring-into-hashmapstring-t-using-stream-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!