java8函数式编程(Lambda表达式,Optional,Stream流)从入门到精通

文章目录

函数式编程

  • 不关心具体的对象,只关心数据参数和 具体操作

Lambda表达式

  • 格式:

    • () -> {}
  • 假如接口只有一个 函数需要被重写,则可以使用 Lambda表达式来 代替 类的创建和重写

  • 省略规则:

    1. 参数类型可以省略
    2. 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略
    3. 方法只有一个参数时小括号可以省略

Stream流

  • 对集合进行操作

创建流

  • 集合对象. stream()

  • 单列集合

    • 数组:

      • 使用 Arrays 数组工具类 来创建

      • 使用 stream.of创建

      java 复制代码
      Integer[] arr = {1,2,3,4,5};
      Stream<Integer> stream = Arrays.stream(arr);
      Stream<Integer> stream2 = Stream.of(arr);
  • 双列集合:

    • 先转换为 Set<Map.Entry<String, String>>,再获取 Stream

    复制代码
      Map<String ,String > map = new HashMap<>();
      Set<Map.Entry<String, String>> entries = map.entrySet();
      Stream<Map.Entry<String, String>> stream = entries.stream();

中间操作

  • distinct

    • 去重
      • 依靠 Objec.equals方法
        • 不重写是 地址相同
  • filter(条件)

    • 条件过滤

      java 复制代码
      list.stream()
              .distinct() //过滤重复元素
              .filter(s -> s.length() <=3)
              .forEach(s -> System.out.println(s));
  • map

    • 转化集合中每个元素的类型:

      java 复制代码
      List<String > list = new ArrayList<>();
      list.add("111");
      list.add("111");
      list.add("2222");
      // forEach
      //过滤条件
      list.stream()
              .map(s -> Integer.valueOf(s))
              .forEach(integer -> System.out.println(integer));
  • sorted 排序

    • 先将流中类型 转换为 Comparable

    • 如果是空参,自定义类型需要实现Comparable接口

      复制代码
        List<String > list = new ArrayList<>();
        list.add("111");
        list.add("333");
        list.add("2222");
        // forEach
        //过滤条件
        list.stream()
                .sorted()
                .forEach(integer -> System.out.println(integer));
    • 还可以传入参数

      复制代码
        list.stream()
                .map(s -> Integer.valueOf(s))
                .sorted(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1-o2;
                    }
                })
                .forEach(integer -> System.out.println(integer));
  • limit:

    • 设置流的最大长度

      复制代码
        list.stream()
                .limit(2)
                .forEach(System.out::println);
  • skip:

    • 跳过前n个元素

      复制代码
        list.stream()
                .skip(2)
                .forEach(System.out::println);
  • flatMap

    • 将流中一个元素 转换成 流元素

      java 复制代码
      List<List<String >> list = new ArrayList<>();
      list.add(Arrays.asList("111","2222"));
      list.add(Arrays.asList("1121","2222"));
      list.add(Arrays.asList("113","2222"));
      // forEach
      //过滤条件
      list.stream()
              .flatMap(strings -> strings.stream())
              .forEach(System.out::println);
      • 输出:

      • 未简化:

        java 复制代码
        //过滤条件
        list.stream()
                .flatMap(new Function<List<String>, Stream<?>>() {
                    @Override
                    public Stream<?> apply(List<String> strings) {
                        return strings.stream();
                    }
                })
                .forEach(System.out::println);

终结操作

  • forEach

    • 对流中元素进行遍历操作
  • count:

    • 获取流中元素的 个数

      java 复制代码
      long count = list.stream()
              .flatMap(strings -> strings.stream())
              .count();
      System.out.println(count);
  • min & max

    • 求流中最值

      • 重写比较方法:

        复制代码
          Optional<Integer> count = list.stream()
                  .flatMap(strings -> strings.stream())
                  .map(s -> Integer.valueOf(s))
                  .max(new Comparator<Integer>() {
                      @Override
                      public int compare(Integer o1, Integer o2) {
                          return o1 - o2;
                      }
                  });
          System.out.println(count);
        • 简化:

          复制代码
            Optional<Integer> count = list.stream()
                    .flatMap(strings -> strings.stream())
                    .map(s -> Integer.valueOf(s))
                    .max((o1, o2) -> o1 - o2);
            System.out.println(count);
  • collect:

    • 转换为list,使用 集合类中的 tolist方法:

      java 复制代码
      List<List<String >> list = new ArrayList<>();
      list.add(Arrays.asList("111","2222"));
      list.add(Arrays.asList("1121","2222"));
      list.add(Arrays.asList("113","2222"));
      List<String> collect = list.stream()
              .flatMap(strings -> strings.stream())
              .collect(Collectors.toList());
      System.out.println(collect);
    • 转换为set,一样:

      复制代码
        Set<String> collect = list.stream()
                .flatMap(strings -> strings.stream())
                .collect(Collectors.toSet());
        System.out.println(collect);
    • 转换为 Map集合

      复制代码
        Map<String, String> collect = list.stream()
                .flatMap(strings -> strings.stream())
                .distinct()
                .collect(Collectors.toMap(s -> s, s -> s));
        System.out.println(collect);
  • 查找:

    • anyMatch

      • 任意一个满足就为 true

        java 复制代码
        boolean b = list.stream()
                .flatMap(strings -> strings.stream())
                .anyMatch(s -> s.length() > 10);
    • allMatch

      • 所有满足才为true
    • noneMatch

      • 都不满足才为 true
  • 匹配:

    • findAny

      • 获取任意一个满足条件的 元素
    • findFirst

      • 获取第一个元素

        复制代码
          List<List<String >> list = new ArrayList<>();
          list.add(Arrays.asList("111","2222"));
          list.add(Arrays.asList("1121","2222"));
          list.add(Arrays.asList("113","2222"));
          Optional<String> first = list.stream()
                  .flatMap(strings -> strings.stream())
                  .sorted()
                  .findFirst();
          first.ifPresent(System.out::println);
  • reduce归并

    • 对流中数据按照指定的计算方式计算出一个结果

    • 原理:

      • 两个参数的重载形式内部的计算方式如下:

      • 一个参数:

        • 把第一个参数 作为 初始化值
    • 使用:

      • 0 : 初始值

      • (result, integer2) -> result + integer2 执行的操作

      java 复制代码
      List<List<String >> list = new ArrayList<>();
      list.add(Arrays.asList("111","2222"));
      list.add(Arrays.asList("1121","2222"));
      list.add(Arrays.asList("113","2222"));
      Integer reduce = list.stream()
              .flatMap(strings -> strings.stream())
              .map(s -> Integer.valueOf(s))
              .reduce(0, (result, integer2) -> result + integer2);

注意事项

  1. 惰性求值
    • 没有终结操作,中间操作不会执行
  2. 流是一次性的
    • 一个流只能执行一次 终结操作
  3. 不会影响原数据

Optional

  • 预防空指针异常

创建对象

  • 使用Optional.ofNullable

    java 复制代码
    String s = new String("1");
    Optional<String> s1 = Optional.ofNullable(s);
    s1.ifPresent(s2 -> System.out.println(s2));
消费值
java 复制代码
s1.ifPresent(s2 -> System.out.println(s2));
获取值
  • orElseGet

    • 为空则使用重写的 返回值

    复制代码
      String s = null;
      Optional<String> s1 = Optional.ofNullable(s);
      System.out.println(s1.orElseGet(() -> "222"));
  • orElseThrow

    • 为空,则抛出异常
过滤
  • filter

    • 假如不满足过滤条件,则返回 Optional.empty

      java 复制代码
      String s = "null";
      Optional<String> s1 = Optional.ofNullable(s);
      Optional<String> s2 = s1.filter(s3 -> s3.length() < 2);
      System.out.println(s2); //打印 Optional.empty
判断
  • isPresent
    • 判断是否存在
数据转换
  • 使用map 进行 Optional类型的转换

    java 复制代码
    String s = "1";
    Optional<String> s1 = Optional.ofNullable(s);
    Optional<Integer> i = s1.map(s2 -> Integer.valueOf(s2));
    i.ifPresent(System.out::println); //1

方法引用

  • 在使用 Lambda 表达式的时候,如果方法体中只有一个方法 的调用话,就可以使用 类名或者对象名::方法名 来简化

高级用法

基本数据类型优化

  • 我们之前用到的很多Stream的方法由于都使用了泛型。

  • 所以涉及到的参数和返回值都是引用数据类型。

  • 即使我们操作的是整数小数,但是实际用的都是他们的包装类

  • JDK5中引入的自动装箱和自动拆箱让我们在使用对应的包装类时就好像使用基本数据类型一样方便。

  • 但是你一定要知道装箱和拆箱肯定是要消耗时间的。

  • 虽然这个时间消耗很下。但是在大量的数据不断的重复装箱拆箱的时候,你就不能无视这个时间损耗了。

  • 所以为了让我们能够对这部分的时间消耗进行优化。

  • Stream还提供了很多专门针对基本数据类型的方法。

  • 例如: mapToInt,mapToLong,mapToDouble,flatMapTolnt,flatMapToDouble等。

    java 复制代码
    List<List<String >> list = new ArrayList<>();
    list.add(Arrays.asList("111","2222"));
    list.add(Arrays.asList("1121","2222"));
    list.add(Arrays.asList("113","2222"));
    list.stream()
            .flatMap(strings -> strings.stream())
            .mapToInt(s -> Integer.valueOf(s))
            .forEach(System.out::println);

并行流

  • 当流中有大量元素时,我们可以使用并行流去提高操作的效率。其实并行流就是把任务分配给多个线程去完全。

  • 如果我们自己去用代码实现的话其实会非常的复杂,并且要求你对并发编程有足够的理解和认识。

  • 而如果我们使用Stream的话,我们只需要修改一个方法的调用就可以使用并行流来帮我们实现,从而提高效率。

  • 使用parallel()

    • peek中间操作

    java 复制代码
    List<List<String >> list = new ArrayList<>();
    list.add(Arrays.asList("111","2222"));
    list.add(Arrays.asList("1121","2222"));
    list.add(Arrays.asList("113","2222"));
    OptionalInt first = list.stream()
        .parallel()
        .flatMap(strings -> strings.stream())
        .mapToInt(s -> Integer.valueOf(s))
        .peek(i -> System.out.println(i + ":" + Thread.currentThread().getName()))
        .findFirst();
    • 打印:
相关推荐
冷雨夜中漫步8 小时前
Python快速入门(6)——for/if/while语句
开发语言·经验分享·笔记·python
郝学胜-神的一滴8 小时前
深入解析Python字典的继承关系:从abc模块看设计之美
网络·数据结构·python·程序人生
百锦再8 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
m0_7369191010 小时前
C++代码风格检查工具
开发语言·c++·算法
喵手10 小时前
Python爬虫实战:旅游数据采集实战 - 携程&去哪儿酒店机票价格监控完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集结果csv导出·旅游数据采集·携程/去哪儿酒店机票价格监控
2501_9449347310 小时前
高职大数据技术专业,CDA和Python认证优先考哪个?
大数据·开发语言·python
玉梅小洋10 小时前
Windows 10 Android 构建配置指南
android·windows
helloworldandy10 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
黎雁·泠崖10 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
2301_7634724611 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法