zoukankan      html  css  js  c++  java
  • Java 函数式编程--流操作

    GitHub Page: http://blog.cloudli.top/posts/Java-函数式编程-流操作/

    外部迭代到内部迭代

    在使用集合类时,通用的方式是在使用 for 循环集合上进行迭代,然后处理每一个元素。比如计算集合中来自上海的用户:

    int count = 0;
    for (User user : allUsers) {
        if (user.isFrom("Shanghai")) {
            count++;
        }
    }
    

    以上代码为外部迭代,这样的方式要写很多样板代码。

    另一种方式是内部迭代:

    long count = allUsers.stream()
                         .filter(user -> user.isFrom("Shanghai"))
                         .count();
    

    整个过程变成了函数调用,且被分解为两个简单的操作:

    • 找出所有来自上海的用户。
    • 计算他们的数量。

    每种操作都对应 Stream 接口的一个方法。为了找出来自上海的用户,需要对 Stream 对象进行过滤:filter() 方法,该方法接受一个 lambda 表达式,最后由 count() 方法计算给定的 Stream 中包含多少对象。

    只调用 filter() 方法并不会做任何操作:

    allUsers.stream()
            .filter(user -> {
                out.println(user.name);
                return user.isFrom("Shanghai")
            });
    

    以上代码不会产生任何输出,只有最后调用了 count() 方法,才能看到输出。filter 方法返回的是一个 Stream 对象,这个过程和建造者模式相似。

    建造者模式通过一系列的操作设置属性,只有最后调用了 build() 方法对象才会被创建。在这里 filter() 方法只是传递了一个 lambda 表达式,只有在 count() 方法被调用时才会去执行它。

    常用的流操作

    filter

    filter() 方法在上一部分已经出现过,它使用给定的 lambda 表达式检查流中的元素,并过滤出符合条件的元素。

    List<User> usersFromShanghai = allUsers.stream()
                    // 过滤出来自上海的用户
                    .filter(user -> user.isFrom("Shanghai"))
                    .collect(Collectors.toList());
    

    filter() 方法的参数是 Predicate 接口:

    Predicate

    collect

    该方法接受一个 Collector 类型的函数式接口。可以结合 Collectors 提供的方法来完成操作。

    将所有来自上海的用户存入一个列表中:

    List<User> usersFromShanghai = allUsers.stream()
                    .filter(user -> user.isFrom("Shanghai"))
                    .collect(Collectors.toList());
    

    统计每个地区用户的数量,这个操作与 SQL 中的 group by 类似。:

    Map<String, Long> userMap = allUsers.stream()
                // 以 User 的 location 进行分组,对每个分组计数
                .collect(Collectors.groupingBy(User::getLocation, Collectors.counting()));
    

    collect() 方法还可以完成很多操作,以上只是其中一种。

    map

    map() 可以将一个流中的值转换为一个新的流。

    将一个字符串列表全部转为大写:

    List<String> list = Stream.of("a", "b", "c")
                              // 将每个字符串转换成大写
                              .map(str -> str.toUpperCase())
                              // 转换为列表
                              .collect(Collectors.toList());
    

    这里传给 map() 的 lambda 表达式接受一个 String 类型的参数,返回一个新的 String。参数和返回值可以不属于同一种类型。

    map() 方法的参数是 Function 函数式接口:

    Function

    flatMap

    flatMap() 将一个流中每一个值都转换为 Stream 对象。

    可以使用该方法将多个列表合并:

    List<Integer> together = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6))
                                   // 将每个列表都转换成 Stream
                                   .flatMap(numbers -> numbers.stream())
                                   // 转换成列表
                                   .collect(Collectors.toList());
    

    flatMap() 方法的参数也是 Function 接口,唯一的区别在于返回值限定为 Stream 类型。

    flatMap Function

    reduce

    reduce() 方法可以实现从一组值中生成一个值。

    对一个列表进行求和:

    int sum = Stream.of(1, 2, 3, 4)
                    .reduce(0, (acc, e) -> acc + e);
    

    对一个列表求阶乘:

    int sum = together.stream()
                      .reduce(1, (acc, e) -> acc * e);
    
  • 相关阅读:
    晕倒的AIX
    MySQL Replication(zt)
    pxe启动网络安装CentOS(win平台)(zt)
    几句比较实用的script
    改注册表方式防DDOS攻击[ZT]
    一个免费空间列表相对集中的地方
    CREE LED的一个小资料
    下一步准备研究的东西:rsync远程同步
    PXE启动安装Linux (zt)
    系统调用
  • 原文地址:https://www.cnblogs.com/cloudfloating/p/11728453.html
Copyright © 2011-2022 走看看