- Lambda 表达式
- 方法引用
- 函数式接口
- 默认方法
- Stream
- Optional 类
- Nashorn, JavaScript 引擎
- 新的日期时间 API
- Base64
1、lambda表达式
1.1、用法举例:
public class LambdaTest {
public static void main(String[] args) {
Hello h = ()->10;
Hello1 h1 = (a,b) -> a+b;
System.out.println(h.sayA());
System.out.println(h1.sayB(3,4));
}
}
interface Hello{
int sayA();
}
interface Hello1{
int sayB(int a,int b);
}
1.2、思考:
1、lambda表达式,相当于接口的实现,而该接口,必须是函数式接口,否则报错Multiple non-overriding abstract methods found in interface com.asiainfo.group.jdk8.Hello
2、lambda表达式提供了函数式编程的能力
3、像lambda表达式、方法引用的返回值一定是函数式接口,而该接口可以自己定义,也可以使用java.util.function包下面已有的类
1.3、语法
lambda 表达式的语法格式如下:
(parameters) -> expression 或 (parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值
1.4、表达式实例
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
2、函数式接口
所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces
函数式接口可以用注解@FunctionalInterface标识
2.1、特点
- 接口有且仅有一个抽象方法
- 允许定义静态方法
- 允许定义默认方法
- 允许java.lang.Object中的public方法
- 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错
2.2、JDK中的函数式接口举例
java.lang.Runnable,
java.awt.event.ActionListener,
java.util.Comparator,
java.util.concurrent.Callable
java.util.function包下的接口,如Consumer、Predicate、Supplier等
2.3、supplier接口的理解
supplier是用来创建对象的,但是不同于传统的创建对象语法
//创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象
Supplier<MethodReferenceTest> s = MethodReferenceTest::new;
//调用get()方法,此时会调用对象的构造方法,即获得到真正对象
MethodReferenceTest m1 = s.get();
System.out.println(m1.hashCode());
//每次get都会调用构造方法,即获取的对象不同
MethodReferenceTest m2 = s.get();
System.out.println(m2.hashCode());
3、方法引用
方法引用可以理解为Lambda表达式的另外一种表现形式
类型 | 语法 | 对应的Lambda表达式 |
---|---|---|
静态方法引用 | 类名::staticMethod | (args) -> 类名.staticMethod(args) |
实例方法引用 | inst::instMethod | (args) -> inst.instMethod(args) |
对象方法引用 | 类名::instMethod | (inst,args) -> 类名.instMethod(args) |
构建方法引用 | 类名::new | (args) -> new 类名(args) |
4、stream api
4.1、流的概念
流是数据渠道
,用于操作数据源
,所生成一种新的元素序列
。集合讲的是数据,流讲的是计算
,是操作
使用Stream API 对集合的数据进行操作
,类似于SQL执行的数据库查询
,也可以用来并行执行
操作,其提供了一种高效且易于使用的处理数据方式
- Stream自身
不会存储元素
- Stream
不会改变数据源对象
,相反会返回产生一个持有结果的新Stream
- Steam操作是
延迟执行
的,这意味着他们会等到需要结果的时候才执行
流的操作步骤:
创建流 -> 中间操作 -> 终止操作
4.2、创建流(创建流的方式)
- 通过Collection 系列集合提供的串行流:stream()、并行流: paralleStream()
-
通过
Arrays
中的静态方法stream(T[] array)
获取数组流
-
通过
Stream类
中的静态方法of()
-
使用
Stream
类的静态方法iterate
创建无限流
-
使用
Stream
类的静态方法generate
创建无限流
4.3、中间操作
一个中间操作链,用Stream API 对数据源数据进行操作处理
注意点:
- 若只有中间操作,则
不会执行
- 只有终止操作执行后,所有的中间操作
一次执行
,此时就称为延迟加载
或者惰性求值
4.3.1、筛选与切片
filter-过滤
limit-限定元素数量
skip-跳过元素
distinct-去重
4.3.2、map映射
接收一个lamda表达式
作为参数,该函数会被应用到每个元素上
,并将其映射到一个新的元素
4.3.3、排序
sorted
4.4、终止操作
4.4.1、查找与匹配
- allMatch-检查是否匹配所有元素
- anyMatch-检查是否至少匹配一个元素
- noneMatch-检查是否所有元素都没有匹配到
- findFirst-返回第一个元素
- findAny-返回当前流中的任意一个元素
- count-返回流中元素总个数
- max-返回流中的最大值
- min-返回流中的最小值
4.4.2、归约与收集
- reduce-将流中元素反复结合起来,得到一个值
- collect-将流转换为其他形式
4.4.3、Collectors类中的常用方法
- counting-统计数量
- averagingDouble-求平均值并转换成Double类型
- summingDouble-求和并转换成Double类型
- maxBy-根据函数条件求最大值
- groupingBy-分组
- partitioningBy-分区
- summarizingDouble-计算方法总括函数
- joining-连接字符串
4.5、stream api综合案例
List<String> list = new ArrayList<>();
list.add("group");
list.add("com");
list.add("jdk8");
list.add("java");
list.add("util");
list.add("");
list.add("util");
list.add("asiainfo");
list.stream().filter(s -> !"".equals(s)).distinct().limit(5).sorted().map(s -> s.toUpperCase())
.forEach(System.out::println);
5、optional 示例
String s1 = "ok";
String s2 = null;
//ofNUllable表示可接受一个null对象,如果使用of来接受null对象则会抛出空指针异常
Optional<String> o1 = Optional.of(s1);
Optional<String> o2 = Optional.ofNullable(s2);
//true表示有值,false表示为空
System.out.println(o1.isPresent());
System.out.println(o2.isPresent());
//如果o2有值,则返回该值;没值,则返回hello
String newS2 = o2.orElse("hello");
//获取值
System.out.println(o1.get());
System.out.println(newS2);
6、List/Set/Map初始化
List<String> list = new ArrayList<String>(){{
add("a");
add("a");
add("a");
}};