Java8-01
【摘要】 1.Lambda 表达式Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。Lambda 表达式的常见结构:BinaryOperator<Integer>add=(×,y)→×+y。函数接口指仅具有单个抽象方法的接口,用来表示 Lambda 表达式的类型。 2.jdk8 增强与新特性Java 8 引入了许多新的语言特性和 API 改进,以下是其中一些主要的特性:Lambda 表达...
1.Lambda 表达式
- Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。
- Lambda 表达式的常见结构:
BinaryOperator<Integer>add=(×,y)→×+y
。 - 函数接口指仅具有单个抽象方法的接口,用来表示 Lambda 表达式的类型。
2.jdk8 增强与新特性
Java 8 引入了许多新的语言特性和 API 改进,以下是其中一些主要的特性:
- Lambda 表达式: Lambda 表达式是一种更简洁的语法,用于表示一个匿名函数。它使得在集合操作、事件处理等场景下代码更具可读性和简洁性。
- 函数式接口: Java 8 引入了函数式接口的概念,这是只包含一个抽象方法的接口。Lambda 表达式可以与函数式接口一起使用。
- 方法引用: 方法引用允许你直接引用现有的方法或构造函数,从而使代码更加简洁。
- 默认方法和静态方法: 接口现在可以包含默认方法和静态方法的实现。这使得在接口中添加新的方法时,不会破坏已有的实现。
- Stream API: Stream API 提供了一种更便捷的方式来处理集合数据。它支持函数式编程风格,可以用于过滤、映射、归约等操作。
- 新的日期和时间 API: Java 8 引入了
java.time
包,提供了全新的日期和时间 API,解决了旧的Date
和Calendar
类存在的问题。 - Optional 类:
Optional
是一个容器类,用于表示一个值可能存在,也可能不存在的情况,从而减少空指针异常的发生。 - Nashorn 引擎: Nashorn 是一个新的轻量级、高性能的 JavaScript 引擎,用于在 Java 程序中执行 JavaScript 代码。
- 新的重复注解和类型注解: 如前所述,Java 8 引入了对多重注解的支持,以及更丰富的类型注解。
- PermGen 空间被移除: Java 8 中,永久代(PermGen)被元空间(Metaspace)所取代,用于存放类的元数据。
3.Stream 的组成与特点
Stream
(流)是一个来自数据源的元素队列并支持聚合操作:
- 元素是特定类型的对象,形成一个队列。
Java
中的Stream
并不会向集合那样存储和管理元素,而是按需计算 - 数据源流的来源可以是集合
Collection
、数组Array
、I/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());
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)