Any way to stream a map like “(k,v)” instead of working with (entry)?

后端 未结 4 1871
北恋
北恋 2020-12-31 04:26

Basically I look for a way to avoid working with

entry -> entry.getValue

and

entry -> entry.getKey

4条回答
  •  长发绾君心
    2020-12-31 04:46

    It's a bit unfortunate that the main way to process a map using streams is to stream the map's entries. That means you have to extracting the entries' keys and values. This is somewhat verbose, but it isn't really all that bad. Still, it might be reasonable to consider some kind of helper methods that will adapt a BiPredicate or BiFunction so that they can be used in the filter or map stages of a stream of map entries. They look like this:

    static  Predicate> p(BiPredicate bip) {
        return entry -> bip.test(entry.getKey(), entry.getValue());
    }
    
    static  Function,R> m(BiFunction bif) {
        return entry -> bif.apply(entry.getKey(), entry.getValue());
    }
    

    Once you have these, you can use them to simplify(?) a map entry stream. Let's say you have a Map and you want to select the entries where the string key's length is greater than the integer value, and then format the key and value into a string. Conventionally you'd do this:

        map.entrySet().stream()
                      .filter(e -> e.getKey().length() > e.getValue())
                      .map(e -> e.getKey() + ":" + e.getValue())
                      .forEach(System.out::println);
    

    With the helper functions above, you could rewrite this pipeline as:

        map.entrySet().stream()
                      .filter(p((k, v) -> k.length() > v))
                      .map(m((k, v) -> k + ":" + v))
                      .forEach(System.out::println);
    

    OK, you save a few characters. Is it worth it?

提交回复
热议问题