【问题标题】:How to Stream a Map by value which is a Collection?如何按集合的值流式传输地图?
【发布时间】:2016-10-20 10:06:01
【问题描述】:

如何流式传输Map<String, List<String>> 以获取:

  1. 所有Strings 中的Strings 的Lists 的值超过5 个字符的Map?如何获得这些的长计数?

  2. 一个Map<String, List<String>>,其中键保持不变,但Lists 仅包含长度大于5 的Strings?

  3. Strings 的 List 每个映射键的计数超过 5 个 Map<String, Long>

我开始了一些事情,但我被卡住了:

long l = map.entrySet().stream()
            .filter(m -> m.getValue().stream().filter(s -> s.length() > 5)

谢谢

【问题讨论】:

    标签: java collections java-8 java-stream


    【解决方案1】:

    对于第一个问题,您可以使用flatMap 合并Lists,然后过滤掉短的Strings:

    List<String> longStrings = 
        map.values()
           .stream()
           .flatMap(Collection::stream)
           .filter(s->s.length() > 5)
           .collect(Collectors.toList());
    

    对于第二个问题,您似乎想从源 Map 创建一个新的 Map,其中键保持不变,值被过滤:

    示例输入:

    Map<String, List<String>> map = new HashMap<> ();
    map.put ("one", Arrays.asList (new String[]{"1","2","12345","123456"}));
    map.put ("two", Arrays.asList (new String[]{"1","123456","12345","12"}));
    map.put ("three", Arrays.asList (new String[]{"1","2","12","34"}));
    map.put ("four", Arrays.asList (new String[]{"12345","123456","1234567","123"}));
    

    处理:

    Map<String, List<String>> output =
        map.entrySet()
           .stream()
           .collect(Collectors.toMap(Map.Entry::getKey,
                                     e->e.getValue()
                                         .stream()
                                         .filter(s -> s.length() > 5)
                                         .collect(Collectors.toList())));
    

    输出:

    {four=[123456, 1234567], one=[123456], three=[], two=[123456]}
    

    第三个问题是第二个问题的微小变化:

    Map<String, Long> output =
        map.entrySet()
           .stream()
           .collect(Collectors.toMap(Map.Entry::getKey,
                                     e->e.getValue()
                                         .stream()
                                         .filter(s -> s.length() > 5)
                                         .count()));
    

    【讨论】:

    • 谢谢。好吧,在第一个问题中,我想返回所有大于 5 的字符串的 List,不管键是什么。第二个我想要 map 就像你在第一个示例中所做的那样,第三个我想要 map 但使用计数而不是列表作为值。再次感谢
    • @Prpaa 编辑回答第一个问题。
    • 如果源Map是可变的并且不需要旧状态,则任务2可以作为就地操作完成:map.values().forEach(list -&gt; list.removeIf(s -&gt; s.length() &lt;= 5));
    • 否则,Java 9 将有必要的内置收集器用于此类任务,即任务 2 的.collect( groupingBy(Map.Entry::getKey, flatMapping(e -&gt; e.getValue().stream(), filtering(s -&gt; s.length() &gt; 5, toList()))))(有点 LISP 感觉),可以轻松适应任务 3通过将toList() 替换为counting()...
    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多