zoukankan      html  css  js  c++  java
  • Java8中map()和flatMap()的区别

    综述

    map()和flatMap()源自于函数式语言,在Java 8中,我们可以在Optional、Stream和CompletableFuture中找到它们(虽然名字稍有不同)。

    stream表示一个对象序列,而optionals表示一个值可以是存在的,也可以是不存在的,在其他aggregate操作中,有map()和flatMap()方法。

    尽管两者具有相同的返回类型,但它们是完全不同的。

    Optionals中的Map和FlatMap

    如果函数返回的正是我们需要的确切类型,那么map()方法可以很好的在Optional中使用。

    Optional<String> s = Optional.of("test");
    assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));

    然而,在更复杂的情况下,我们可能会得到一个返回Optional的函数。在这种情况下,使用map()会导致嵌套结构,因为map()实现在内部进行了额外的包装。

    assertEquals(Optional.of(Optional.of("STRING")), 
      Optional
      .of("string")
      .map(s -> Optional.of("STRING")));

    通过map我们得到了一个嵌套的结构,尽管它可以工作,但使用起来相当繁琐,而且没有提供任何额外的null安全性,所以最好应该保持flat的数据结构。

    assertEquals(Optional.of("STRING"), Optional
      .of("string")
      .flatMap(s -> Optional.of("STRING")));

    Stream中的Map和Flatmap

    map()方法将底层序列包装在Stream实例中,而flatMap()方法可以避免嵌套的Stream<Stream<R>>结构。

    map()生成一个流,其中包含对输入流的元素应用toUpperCase()方法的结果

    List<String> myList = Stream.of("a", "b")
      .map(String::toUpperCase)
      .collect(Collectors.toList());
    assertEquals(asList("A", "B"), myList);

    如下为将一个列表的列表作为输入:

    List<List<String>> list = Arrays.asList(
      Arrays.asList("a"),
      Arrays.asList("b"));
    System.out.println(list);
    
    //output: [[a], [b]]

    使用flatMap,结果将扁平化为 [a,b]

    System.out.println(list
      .stream()
      .flatMap(Collection::stream)
      .collect(Collectors.toList()));

    flatMap()方法首先将list输入流扁平化为字符串流,此后它的工作方式类似于map()。

    扁平化嵌套的集合

    嵌套集合的示例

    假设有一个String类型列表的列表:

    List<List<String>> nestedList = asList(
      asList("one:one"), 
      asList("two:one", "two:two", "two:three"), 
      asList("three:one", "three:two", "three:three", "three:four"));

    用forEach扁平化List

    为了将这个嵌套集合扁平化为一个字符串列表,可以将forEach与Java 8方法引用一起使用

    public <T> List<T> flattenListOfListsImperatively(
        List<List<T>> nestedList) {
        List<T> ls = new ArrayList<>();
        nestedList.forEach(ls::addAll);
        return ls;
    }
    @Test
    public void givenNestedList_thenFlattenImperatively() {
        List<String> ls = flattenListOfListsImperatively(nestedList);
        
        assertNotNull(ls);
        assertTrue(ls.size() == 8);
        assertThat(ls, IsIterableContainingInOrder.contains(
          "one:one",
          "two:one", "two:two", "two:three", "three:one",
          "three:two", "three:three", "three:four"));
    }

    用flatMap扁平化List

    还可以利用Stream API中的flatMap方法使嵌套列表扁平化,这个方法允许我们扁平嵌套的Stream结构,并最终将所有元素收集到一个特定的集合中。

    public <T> List<T> flattenListOfListsStream(List<List<T>> list) {
        return list.stream()
          .flatMap(Collection::stream)
          .collect(Collectors.toList());    
    }
    @Test
    public void givenNestedList_thenFlattenFunctionally() {
        List<String> ls = flattenListOfListsStream(nestedList);
        
        assertNotNull(ls);
        assertTrue(ls.size() == 8);
    }

     

  • 相关阅读:
    记录log中的16进制和ASCII码字符输出
    有效的沟通技巧
    时间的真谛
    目标设定与时间管理
    第四代时间管理
    什么是高效沟通
    error LNK1104: cannot open file 错误解决方案
    js压缩工具1.0界面绘制
    时间管理的定义与目的
    JArgs命令行选项解析>Java套件
  • 原文地址:https://www.cnblogs.com/CodePastry/p/14905232.html
Copyright © 2011-2022 走看看