【Java8系列01】JDK8 的增强

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

1.Lambda 表达式

  • Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。
  • Lambda 表达式的常见结构:BinaryOperator<Integer>add=(×,y)→×+y
  • 函数接口指仅具有单个抽象方法的接口,用来表示 Lambda 表达式的类型。

2.jdk8 增强与新特性

Java 8 引入了许多新的语言特性和 API 改进,以下是其中一些主要的特性:

  1. Lambda 表达式: Lambda 表达式是一种更简洁的语法,用于表示一个匿名函数。它使得在集合操作、事件处理等场景下代码更具可读性和简洁性。
  2. 函数式接口: Java 8 引入了函数式接口的概念,这是只包含一个抽象方法的接口。Lambda 表达式可以与函数式接口一起使用。
  3. 方法引用: 方法引用允许你直接引用现有的方法或构造函数,从而使代码更加简洁。
  4. 默认方法和静态方法: 接口现在可以包含默认方法和静态方法的实现。这使得在接口中添加新的方法时,不会破坏已有的实现。
  5. Stream API: Stream API 提供了一种更便捷的方式来处理集合数据。它支持函数式编程风格,可以用于过滤、映射、归约等操作。
  6. 新的日期和时间 API: Java 8 引入了 java.time 包,提供了全新的日期和时间 API,解决了旧的 DateCalendar 类存在的问题。
  7. Optional 类: Optional 是一个容器类,用于表示一个值可能存在,也可能不存在的情况,从而减少空指针异常的发生。
  8. Nashorn 引擎: Nashorn 是一个新的轻量级、高性能的 JavaScript 引擎,用于在 Java 程序中执行 JavaScript 代码。
  9. 新的重复注解和类型注解: 如前所述,Java 8 引入了对多重注解的支持,以及更丰富的类型注解。
  10. PermGen 空间被移除: Java 8 中,永久代(PermGen)被元空间(Metaspace)所取代,用于存放类的元数据。

3.Stream 的组成与特点

Stream(流)是一个来自数据源的元素队列并支持聚合操作:

  • 元素是特定类型的对象,形成一个队列。Java中的Stream不会向集合那样存储和管理元素,而是按需计算
  • 数据源流的来源可以是集合Collection、数组ArrayI/O channel, 产生器generator
  • 聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted

和以前的Collection操作不同, Stream 操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。这样做可以对操作进行优化, 比如延迟执行(laziness evaluation)和短路( short-circuiting)
  • 内部迭代:以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。Stream提供了内部迭代的方式, 通过访问者模式 (Visitor)实现。

和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。

4.Stream 底层原理

示例代码:

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);
    }

}
javap -c -p Java8_01_Source_Main  查看class文件
> 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."<init>":()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."<init>":()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
}

分析结论:

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

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

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

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

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

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

5.回调函数

#回调函数的写法  有套路的
#消息确认成功回调函数
ConfirmCallback ackCallback (deliveryTag,multiple)->{
}:
#消息确认失败回调函数
ConfirmCallback nackCallback (deliveryTag,multiple)->(
#准备消息的监听器监听哪些消息成功了哪些消息失败了
#异步通知
channel..addConfirmListener(ackCallback,nackCallback);

6.flatMap

public static void main(String[] args) {
        List<Integer> lista = new ArrayList<>();
        lista.add(1);
        lista.add(3);

        List<Integer> listb = new ArrayList<>();
        listb.add(2);
        listb.add(4);
        List<List<Integer>> listc = new ArrayList<>();
        listc.add(lista);
        listc.add(listb);
        System.out.println(listc);
        List<Integer> listd = listc.stream().flatMap(ele -> ele.stream()).collect(Collectors.toList());
        System.out.println(listd);
    }

Map<String,List<Object>>使用java8转为 List<Object>

public static void main(String[] args) {
        Map<String, List<Integer>> map = new HashMap<>();
        map.put("1", Arrays.asList(1, 2, 3));
        map.put("2", Arrays.asList(4, 5, 6));
        map.put("3", Arrays.asList(7, 8, 9));
        // 假设已经将数据存储到map中
        List<Integer> list = map.values().stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
        // 将所有List<Object>对象中的元素合并成一个Stream,并将所有元素收集到一个新的List<Object>中
        log.info(list.toString());
    }
final List<StoreSkuInvSalDTO> collect = groupName_2_salDatas.values().stream()
                .flatMap(x -> x.getProducts().stream())
                .collect(Collectors.toList());

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kwan的解忧杂货铺@新空间代码工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值