使用Stream处理Map

1.概述

讨论如何使用Java Streams来处理Maps。

2.基本概念

要注意的主要事情是,流是可以从Collection中轻松获得的元素序列。

Map具有不同的结构,从键到值的映射没有顺序。 但是,这并不意味着无法将Map结构转换为不同的序列,从而无法自然地使用Stream API。

从Map获取不同Collection的方法,然后我们可以将其转变为Stream:

Map<String, Integer> someMap = new HashMap<>();

可以获得一组键值对:

Set<Map.Entry<String, Integer>> entries = someMap.entrySet();

可以获取与Map关联的key集合:

Set<String> keySet = someMap.keySet();

或者可以直接使用一组Vlaues:

Collection<Integer> values = someMap.values();

这些都提供了一个从它们那里获取流来处理这些集合的切入点:

Stream<Map.Entry<String, Integer>> entriesStream = entries.stream();
Stream<Integer> valuesStream = values.stream();
Stream<String> keysStream = keySet.stream();

3.使用流获取Map的键

3.1.数据准备

Map<String, String> books = new HashMap<>();
books.put(
"978-0201633610", "设计模式");
books.put(
  "978-1617291999", "java8实战");
books.put("978-0134685991", "Effective Java");

由于书名在的Map中不存在,能够指出没有相关的ISBN。 可以使用Optional来表示:

  Optional<String> optionalIsbn = books.entrySet().stream()
                .filter(e -> "Effective Java".equals(e.getValue()))
                .map(Map.Entry::getKey)
                .findFirst();

        assertEquals("978-0134685991", optionalIsbn.get());

分析一下代码。 首先,从Map中获得entrySet。

只想考虑以“ Effective Java”作为标题的条目,因此第一个中间操作将是一个过滤器。

对整个Map条目不感兴趣,但对每个条目的键都不感兴趣。 因此,下一个链接的中间操作就是这样做的:这是一个映射操作,它将生成一个新的流作为输出,其中将仅包含与我们要查找的标题匹配的条目的键。

因为只想要一个结果,所以可以应用findFirst()终端操作,该操作将在Stream中提供初始值作为Optional对象。

看一个标题不存在的情况:

    Optional<String> optionalIsbn = books.entrySet().stream()
                .filter(e -> "码出高效".equals(e.getValue()))
                .map(Map.Entry::getKey).findFirst();

        assertEquals(false, optionalIsbn.isPresent());

3.2检索多个结果

如何处理返回多个结果而不是一个结果。

要返回多个结果,让将以下书籍添加到Map中:

books.put("978-0321356680", "Effective Java:第二版");

如果查找所有以“ Effective Java”开头的书籍,将获得不止一个结果:

 List<String> isbnCodes = books.entrySet().stream()
                .filter(e -> e.getValue().startsWith("Effective Java"))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        assertTrue(isbnCodes.contains("978-0321356680"));
        assertTrue(isbnCodes.contains("978-0134685991"));

在这种情况下,要做的是替换过滤条件,以验证Map中的值是否以“ Effective Java”开头,而不是比较String相等性。

这次收集结果,而不只是挑选第一个结果,然后将匹配项放入列表中。

4.使用流获取Map的值

Map的另一个问题。 除了尝试根据标题获取ISBN之外,还将尝试根据ISBN获取标题。

使用原始Map。 希望找到以“ 978-0”开头的ISBN的标题。

       List<String> titles = books.entrySet().stream()
                .filter(e -> e.getKey().startsWith("978-0"))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        assertEquals(3, titles.size());
        assertTrue(titles.contains(
                "设计模式"));
        assertTrue(titles.contains("Effective Java"));

该解决方案类似于先前的问题的解决方案。 流输入条目,然后过滤,映射和收集。
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值