• 【java8】Stream底层原理解析


    Stream底层原理解析

    1.示例代码

    public class Java8_01_Source_Main {
    
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("Red");
            list.add("Green");
            list.add("Blue");
            long lengthyColors = list.stream().filter(c -> c.length() > 3).count();
            System.out.println(lengthyColors);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    javap -c -p Java8_01_Source_Main  查看class文件
    
    • 1
    > javap -c -p  Java8_01_Source_Main
    警告: 二进制文件Java8_01_Source_Main包含com.xiaofei.antjava8.源码.Java8_01_Source_Main
    Compiled from "Java8_01_Source_Main.java"
    public class com.xiaofei.antjava8.源码.Java8_01_Source_Main {
      public com.xiaofei.antjava8.源码.Java8_01_Source_Main();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: new           #2                  // class java/util/ArrayList
           3: dup
           4: invokespecial #3                  // Method java/util/ArrayList."":()V
           7: astore_1
           8: aload_1
           9: ldc           #4                  // String Red
          11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
          16: pop
          17: aload_1
          18: ldc           #6                  // String Green
          20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
          25: pop
          26: aload_1
          27: ldc           #7                  // String Blue
          29: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
          34: pop
          35: aload_1
          36: invokeinterface #8,  1            // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
          41: invokedynamic #9,  0              // InvokeDynamic #0:test:()Ljava/util/function/Predicate;
          46: invokeinterface #10,  2           // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
          51: invokeinterface #11,  1           // InterfaceMethod java/util/stream/Stream.count:()J
          56: lstore_2
          57: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
          60: lload_2
          61: invokevirtual #13                 // Method java/io/PrintStream.println:(J)V
          64: return
    
      private static boolean lambda$main$0(java.lang.String);  // c -> c.length() > 3
        Code:
           0: aload_0
           1: invokevirtual #14                 // Method java/lang/String.length:()I
           4: iconst_3
           5: if_icmple     12
           8: iconst_1
           9: goto          13
          12: iconst_0
          13: ireturn
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    2.分析结论

    通过字节码可以看到 invokedynamic 指令以某种方式负责创建 Predicate 实例。

    此方法以 字符串 作为输入,然后执行以下步骤:

    • 计算输入长度(invokevirtual on length)
    • 将长度与常量 3 进行比较(if_icmple 和 iconst_3)
    • 如果长度小于或等于 3,则返回 false

    Java 7中之前,JVM只是有四个方法调用类型:

    • invokevirtual 调用正常类方法,
    • invokestatic 调用静态方法,
    • invokeinterface 调用接口的方法,
    • invokespecial 调用构造函数或私有方法。

    对于lambda表达式,Java 不是在编译时创建匿名内部类,而是在运行时通过调用动态创建它们

  • 相关阅读:
    Springboot集成websocket实现消息推送和在线用户统计
    SpringBoot使用Nacos作为配置中心服务
    springboot常用组件的集成
    Spring Boot中如何优雅地实现异步调用?
    uniapp apple 苹果登录 离线本地打包
    redis key的删除淘汰策略
    GO语言gin框架实战-03-swagger和接口文档
    HTML5期末考核大作业——学生网页设计作业源码HTML+CSS+JavaScript 中华美德6页面带音乐文化
    springboot配置log4j2
    如何在业务逻辑中引入重试机制:spring-Retry和Guava-Retry
  • 原文地址:https://blog.csdn.net/qyj19920704/article/details/126005615