JDK8新特性

1 Lambda表达式

​ Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
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
package jdk8;

public class LambdaTest {
public static void main(String[] args) {
LambdaTest test = new LambdaTest();

// 类型声明
MathOperation addition = (int a, int b) -> a + b;
System.out.println("10 + 5 = " + test.operate(10, 5, addition));

// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
System.out.println("10 - 5 = " + test.operate(10, 5, subtraction));

// 加大括号
MathOperation multiplication = (int a, int b) -> { return a * b; };
System.out.println("10 * 5 = " + test.operate(10, 5, multiplication));

// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 / 5 = " + test.operate(10, 5, division));

// 不用括号
GreetingService greetingService = message -> System.out.println("hello " + message);
// 用括号
GreetingService greetingService1 = (message) -> System.out.println("hello " + message);

greetingService.sayMessage("world");
greetingService1.sayMessage("world");
}

interface GreetingService {
void sayMessage(String message);
}

interface MathOperation {
int operation(int a, int b);
}

private int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}

运行结果

image-20220309203447439

2 方法引用

​ 方法引用通过方法的名字来指向一个方法。

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
package jdk8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

public class MethodTest {
public static void main(String[] args) {
// 构造器引用
final Car car = Car.create( Car::new );

final List<Car> cars = Arrays.asList(car);
// 静态方法引用
cars.forEach(Car::collide);
// 特定类的任意对象的方法引用
cars.forEach(Car::repair);
// 特定对象的方法引用
final Car police = Car.create(Car::new);
cars.forEach(police::follow);
}
}

class Car {
public Car() {
System.out.println("hello car");
}

public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}

public static void collide(final Car car) {
System.out.println("Collied " + car.toString());
}

public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}

public void repair() {
System.out.println("Repaired " + this.toString());
}
}

运行结果

image-20220309204036736

3 函数式接口

​ 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

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
package jdk8;

import javax.xml.transform.Source;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class FunctionInterfaceTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

// Predicate<Integer> predicate = n -> true
System.out.println("输出所有数据:");

// 传递参数
eval(list, n->true);

// Predicate<Integer> predicate1 = n -> n % 2 == 0
// n 是一个参数传递到 Predicate 接口的test方法
// 如果 n 大于 3 test方法返回true
System.out.println("输出所有偶数:");
eval(list, n-> n%2 == 0);

// Predicate<Integer> predicate2 = n -> n > 3;
// n 是一个参数传递到 Predicate 接口的test方法
// 如果 n 大于 3 test 方法返回true
System.out.println("输出大于3的所有数字:");
eval(list, n-> n > 3);
}

public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for (Integer n : list) {
if (predicate.test(n)) {
System.out.print(n + " ");
}
}
System.out.println("");
}
}

运行结果

image-20220309204453398

4 默认方法

​ 默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

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
package jdk8;

public class DefaultMethod {
public static void main(String[] args) {
Vehicle vehicle = new Car();
vehicle.print();
}

interface Vehicle {
default void print() {
System.out.println("我是一辆车");
}

static void blowHorn() {
System.out.println("按喇叭!!!");
}
}

interface FourWheeler {
default void print() {
System.out.println("我是一辆四轮车!");
}
}

static class Car implements Vehicle, FourWheeler {

@Override
public void print() {
Vehicle.super.print();
FourWheeler.super.print();
Vehicle.blowHorn();
System.out.println("我是一辆汽车!");
}
}
}

运行结果

image-20220309204600796

5 Stream

​ Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

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
package jdk8;

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.stream.Collectors;

public class StreamTest {
public static void main(String[] args) {
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
long count = strings.stream().filter(string -> string.isEmpty()).count();
System.out.println("空字符串数量为:" + count);

count = strings.stream().filter(string -> string.length() == 3).count();
System.out.println("字符串长度为3的数量为:" + count);

List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选后的列表:" + filtered);

String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));
System.out.println("合并字符串:" + mergedString);

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList());
System.out.println("Squares List:" + squaresList);

List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
IntSummaryStatistics statistics = integers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println(statistics);
}
}

运行结果

image-20220309204648855

6 Optional

​ Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

​ Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

​ Optional 类的引入很好的解决空指针异常。

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
package jdk8;

import java.util.Optional;

public class OptionalTest {
public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Integer value1 = null;
Integer value2 = new Integer(10);
// Optional.ofNullable - 允许传递为 null 参数
Optional<Integer> a = Optional.ofNullable(value1);
// Optional.of - 允许传递的参数是null,抛出异常NullPointerException
Optional<Integer> b = Optional.of(value2);
System.out.println(optionalTest.sum(a, b));
}

public Integer sum(Optional<Integer> a, Optional<Integer> b) {
// Optional.isPresent - 判断值是否存在
System.out.println("第一个参数值存在:" + a.isPresent());
System.out.println("第二个参数值存在:" + b.isPresent());

// Optional.orElse - 如果值存在,返回它,否则返回默认值
Integer value1 = a.orElse(new Integer(0));
// Optional.get - 获取值,值需要存在
Integer value2 = b.get();
return value1 + value2;
}
}

运行结果

image-20220309204752631

参考

Java 8 新特性 | 菜鸟教程 (runoob.com)


JDK8新特性
https://2w1nd.github.io/2022/03/09/Java/JDK8新特性/
作者
w1nd
发布于
2022年3月9日
许可协议