Lambda表达式(Java8)
Lambda表达式
Lambda表达式简介
Lambda表达式是Java 8引入的一项重要的新特性,主要受到函数式编程思想的影响。函数式编程思想强调的是对数据进行操作的方式,而不关注具体的对象是什么。Lambda表达式可以被理解为一种匿名函数,它基于数学中的λ演算而得名,也可以称为闭包(Closure)。
- 优点:简化代码,开发迅速,使得函数式编程更加方便。
- 缺点:代码可读性变差,不容易进行调试。
Lambda表达式语法
Lambda表达式由Lambda参数、箭头符号(->)和方法体组成,语法如下
1
| ( paramaters ) -> { 主体部分 }
|
| 组成 | 简介 |
|---|
| paramaters | Lambda参数列表,可以有零个或多个参数,参数类型可以显式指定,也可以由编译器根据上下文自动推断。 如果没有参数,则可以使用空括号()表示; 如果只有一个参数,可以省略参数的括号; 如果有多个参数,需要使用括号()包裹,并用逗号将参数分隔。 |
| -> | 箭头操作符,可理解为“被用于”的意思,用于分隔参数列表与Lambda表达式的主体部分 |
| 主体部分 | 可以是一个表达式,也可以是一个代码块。 如果是一个表达式,则可以省略return关键字,返回一个值或者什么都不返回,等同于方法的方法体; 如果是一个代码块,则需要使用花括号将多个语句括起来,并且需要显式使用return语句来返回值。 |
Lambda表达式省略规则
省略参数类型:如果可以通过上下文推断出参数的类型,可以省略参数的类型,如果需要省略,每个参数的类型都要省略。
1 2 3 4 5 6 7 8 9
| Function<Integer, String> converter = (Integer num) -> { return Integer.toString(num); };
Function<Integer, String> converter = (num) -> { return Integer.toString(num); };
|
省略参数括号:当只有一个参数时,可以省略参数的括号。
1 2 3 4 5 6 7 8 9
| Consumer<String> printer = (String message) -> { System.out.println(message); };
Consumer<String> printer = message -> { System.out.println(message); };
|
省略花括号:如果Lambda表达式只有一条语句,并且没有返回值,可以省略花括号。
1 2 3 4 5 6 7
| Runnable runnable = () -> { System.out.println("Hello World"); };
Runnable runnable = () -> System.out.println("Hello World");
|
省略return关键字:如果Lambda表达式只有一条语句,并且有返回值,可以省略return关键字。
1 2 3 4 5 6 7
| Function<Integer, Integer> square = (Integer num) -> { return num * num; };
Function<Integer, Integer> square = num -> num * num;
|
函数式接口
有且只有一个抽象方法的接口,称为函数式接口(Functional Interface)。在Java中,Lambda表达式是对函数式接口的一种简写方式,只有一个接口是函数式接口时,才能用Lambda表达式。
内置四大核心函数式接口
在Java 8中,提供了四个内置的核心函数式接口,它们分别是:Function、Predicate、Consumer和Supplier。
| 函数式接口 | 用途 |
|---|
Function<T,R> | 函数型接口,接受一个输入参数 T,并返回一个输出结果 R。 |
Predicate<T> | 断定型接口。接受一个输入参数 T,并返回一个布尔值。 |
Consumer<T> | 消费型接口,接受一个输入参数 T,但没有返回值。 |
Supplier<T> | 供给型接口,返回类型为T的对象,包含方法:T get() |
其他函数式接口
| 函数式接口 | 用途 |
|---|
ToIntFunction<T> | 计算int值的函数 |
ToLongFunction<T> | 计算long值的函数 |
ToDoubleFunction<T> | 计算double值的函数 |
IntFunction<R> | 参数为int类型的函数 |
LongFunction<R> | 参数为long类型的函数 |
DoubleFunction<R> | 参数为double 类型的函数 |
自定义函数式接口
如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。其中@FunctionalInterface注解用于检测接口是否是函数式接口,即检查接口是否只有一个抽象方法,如果有两个抽象方法,程序编译就会报错。
1 2 3 4 5 6 7 8
|
@FunctionalInterface interface MyFunctionalInterface<T> { T doSomething(); }
|
Lambda表达式六种使用情况
无参无返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @FunctionalInterface interface NoParameterNoReturn { void methodExample(); }
public class LambdaExample { public static void main(String[] args) { NoParameterNoReturn noParameterNoReturn1 = new NoParameterNoReturn() { @Override public void methodExample() { System.out.println("无参数无返回值!"); } }; noParameterNoReturn1.methodExample();
NoParameterNoReturn noParameterNoReturn2 = () -> System.out.println("无参数无返回值!"); noParameterNoReturn2.methodExample(); } }
|
无参有返回值
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
| @FunctionalInterface interface NoParameterReturn { int methodExample(); }
public class LambdaExample { public static void main(String[] args) { NoParameterReturn noParameterReturn1 = new NoParameterReturn() { @Override public int methodExample() { System.out.println("无参数有返回值!"); return 100; } }; System.out.println("返回值:" + noParameterReturn1.methodExample());
NoParameterReturn noParameterReturn = () -> { System.out.println("无参数有返回值!"); return 100; }; System.out.println("返回值:" + noParameterReturn1.methodExample()); } }
|
一参数无返回值
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
| @FunctionalInterface interface OneParameterNoReturn { void methodExample(int num); }
public class LambdaExample { public static void main(String[] args) { OneParameterNoReturn oneParameterNoReturn1 = new OneParameterNoReturn() { @Override public void methodExample(int num) { System.out.println("一参无返回值,参数:" + num); } }; oneParameterNoReturn1.methodExample(100);
OneParameterNoReturn oneParameterNoReturn = (int num) -> { System.out.println("一参无返回值,参数:" + num); }; oneParameterNoReturn.methodExample(100); } }
|
一参数有返回值
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
| @FunctionalInterface interface OneParameterReturn { int methodExample(int num); }
public class LambdaExample { public static void main(String[] args) { OneParameterReturn oneParameterReturn1 = new OneParameterReturn() { @Override public int methodExample(int num) { System.out.println("一参有返回值,参数:" + num); return num * 2; } }; System.out.println("返回值:" + oneParameterReturn1.methodExample(100));
OneParameterReturn oneParameterReturn2 = (int num) -> { System.out.println("一参有返回值,参数:" + num); return num * 2; }; System.out.println("返回值:" + oneParameterReturn2.methodExample(100)); } }
|
多参数无返回值
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
| @FunctionalInterface interface MoreParameterNoReturn { void methodExample(int num1, int num2); }
public class LambdaExample { public static void main(String[] args) { MoreParameterNoReturn moreParameterNoReturn1 = new MoreParameterNoReturn() { @Override public void methodExample(int num1, int num2) { System.out.println("多参无返回值,参数一:" + num1 + ",参数二:" + num2); } }; moreParameterNoReturn1.methodExample(50, 50);
MoreParameterNoReturn moreParameterNoReturn2 = (int num1, int num2) -> { System.out.println("多参无返回值,参数一:" + num1 + ",参数二:" + num2); }; moreParameterNoReturn2.methodExample(50, 50); } }
|
多参有返回值
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
| @FunctionalInterface interface MoreParameterReturn { int methodExample(int num1, int num2); }
public class LambdaExample { public static void main(String[] args) { MoreParameterReturn moreParameterReturn1 = new MoreParameterReturn() { @Override public int methodExample(int num1, int num2) { System.out.println("多参无返回值,参数一:" + num1 + ",参数二:" + num2); return num1 + num2; } }; System.out.println("返回值:" + moreParameterReturn1.methodExample(50, 50));
MoreParameterReturn moreParameterReturn2 = (int num1, int num2) -> { System.out.println("多参无返回值,参数一:" + num1 + ",参数二:" + num2); return num1 + num2; }; System.out.println("返回值:" + moreParameterReturn2.methodExample(50, 50)); } }
|
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
| public class LambdaExample {
@Test public void methodExample() { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.forEach((number) -> MyMathUtils.printSquare(number));
numbers.forEach(MyMathUtils::printSquare); }
static class MyMathUtils {
static void printSquare(int number) { System.out.println(number * number); } } }
|
方法引用形式二:实例方法引用
使用实例来引用实例方法,语法如下
代码示例
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
| public class LambdaExample {
@Test public void methodExample() {
Person person = new Person("Alice"); Consumer<Person> greeting = Person::sayHello; greeting.accept(person); }
@Data @NoArgsConstructor @AllArgsConstructor class Person { private String name;
public void sayHello() { System.out.println("Hello, " + name); } } }
|
方法引用形式三:对象方法引用
使用类名来引用实例方法,语法如下
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class LambdaExample {
@Test public void methodExample() { Consumer<String> printMessage = message -> System.out.println(message); printMessage.accept("Hello World!");
Consumer<String> printUpperCase = System.out::println; printUpperCase.accept("Hello World!"); } }
|
方法引用形式四:构造方法引用
使用类名和 new 关键字来引用构造函数,语法如下
代码示例
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
| public class LambdaExample {
@Test public void methodExample() { Supplier<Person> personSupplier1 = () -> new Person(); Person person1 = personSupplier1.get(); person1.setName("小明"); System.out.println(person1.getName());
Supplier<Person> personSupplier2 = Person::new; Person person2 = personSupplier2.get(); person2.setName("小明"); System.out.println(person2.getName()); }
@Data @NoArgsConstructor @AllArgsConstructor class Person { private String name; } }
|
Stream流(Java8)
Stream流简介
(1)Stream流结合了Lambda表达式,用于简化集合、数组操作的API
(2)Stream 和 Collection 集合的区别
| 对比 | 区别 |
|---|
| Collection | 是一种静态的内存数据 结构,面向内存,存储在内存中 |
| Stream | 用于操作数据源(集合、数组等)所生成的元素序列,面向 CPU,通过 CPU 实现计算 |
(3)Stream流使用流程
| 流程 | 简介 |
|---|
| 创建流 | 将数据源转换为Stream流 |
| 操作流 | 中间操作链,对数据源的数据进行处理(过滤、聚合等) |
| 结束流 | 终止操作,执行中间操作链,并产生结果 |
Stream流创建的五种方式
通过集合创建Stream流(最常用)
通过集合创建Stream流(最常用),Java8 中的 Collection 接口被扩展,提供了两个获取流的方法
| 方法 | 简介 |
|---|
stream() | 返回一个顺序流 |
parallelStream() | 返回一个并行流 |
1 2 3 4 5 6 7 8 9 10 11
| @Test public void test1() { ArrayList list = new ArrayList(); list.add(1); list.add(2); list.add(3); Stream stream1 = list.stream(); Stream stream2 = list.parallelStream(); }
|
通过数组创建Stream流
通过数组创建Stream流,Java8 中的 Arrays 的静态方法 stream() 可以获取数组流
| 方法 | 简介 |
|---|
| stream(T[] array) | 返回一个流 |
1 2 3 4 5 6
| @Test public void test2() { int[] ints = {}; IntStream stream = Arrays.stream(ints); }
|
通过Stream本身创建Stream流
通过Stream本身创建Stream流,调用Stream类静态方法 of(),通过显示值创建一个流,可以接收任意数量的参数
1 2 3 4 5
| @Test public void test3() { Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5); }
|
通过函数创建Stream无限流
通过函数创建Stream无限流,使用静态方法 Stream.iterate() 和 Stream.generate()创建无限流
| 方法 | 简介 |
|---|
| iterate(final T seed, final UnaryOperatorf) | 迭代,指定一个常量seed,生成从seed到常量f的流 |
| generate(Suppliers) | 生成,返回无限顺序无序流,其中每个元素由提供的供应商生成,适用于生成恒定流,随机元素流等 |
1 2 3 4 5 6 7
| @Test public void test4() { Stream<Integer> iterate = Stream.iterate(0, n -> n + 2); Stream<Double> generate = Stream.generate(Math::random); }
|
通过文件创建Stream流
通过文件创建Stream流,通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行
1 2 3 4 5 6 7 8
| @Test public void test5() { try { Stream<String> fileStream = Files.lines(Paths.get("test.txt"), Charset.defaultCharset()); } catch (IOException e) { e.printStackTrace(); } }
|
Stream流中间操作链
中间操作链简介
(1)通常对于Stream的中间操作,可以视为是源的查询,与数据库中视图的原理相似;
(2)Stream流的强大之处便是在于提供了丰富的中间操作,相比集合或数组这类容器,极大的简化源数据的计算复杂度
多个中间操作可以连接起来形成一个流水线,在终止操作时一次性全部处理,否则中间操作不会执行任何的处理,称为“惰性求值”
(3)一个流可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用,这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终止操作时
筛选与切片
| 流方法 | 含义 |
|---|
filter(Predicate p) | 过滤,接收 Lambda,通过设置的条件,从流中排除某些元素 |
distinct() | 去重,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 |
limit(long maxSize) | 截断,返回一个不超过给定长度的流 |
| skip(long n) | 跳过,返回一个扔掉了前 n 个元素的流,若流中元素不足 n 个,则返回一 个空流,与 limit(n) 互补 |
| peek(Predicate p) | 处理,对元素进行遍历处理 |
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 52 53
| public class Demo {
@Test public void test1() { List<User> userList = User.getUserList(); userList.stream().filter(user -> user.getId() > 5).forEach(System.out::println); }
@Test public void test2() { List<User> userList = User.getUserList(); userList.stream().limit(5).forEach(System.out::print); }
@Test public void test3() { List<User> userList = User.getUserList(); userList.stream().skip(5).forEach(System.out::println); }
@Test public void test4() { List<User> userList = User.getUserList(); userList.stream().distinct().forEach(System.out::println); }
@Test public void test6() { List<User> userList = User.getUserList(); userList.stream().peek(user -> user.setId(user.getAge() + 1)).forEach(System.out::println); }
}
|
映射
| 流方法 | 含义 |
|---|
map(Function f) | 对流中每一个元素进行处理,返回一个值 接受一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素 |
flatMap(Function f) | 流扁平化,将一个整体拆成一个一个的个体,称为扁平化(拆分层级,放到同一层) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
| mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。 |
| mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。 |
| mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream。 |
map(Function f)与flatMap(Function f)的区别与应用场景
| 流方法 | 本质区别 |
|---|
| map(Function f) | 对一级元素进行操作,返回一个值 |
| flatMap(Function f) | 对二级元素操作,返回一个流,多个值 |
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| public class Demo {
private static List<List<Integer>> getList() { List<Integer> integers = Arrays.asList(1, 2, 3); List<List<Integer>> lists = new ArrayList<>(); lists.add(integers); lists.add(integers); return lists; }
@Test public void test1() { List<String> arrayList = Arrays.asList("a", "b", "c"); arrayList.stream().map(str -> str.toUpperCase()).forEach(System.out::print); }
@Test public void test2() { String[] words = new String[]{"Hello", "World"}; Arrays.stream(words) .map(str -> str.split("")) .flatMap( Arrays::stream ) .forEach(System.out::print); }
@Test public void test3() { List<List<Integer>> lists = getList(); lists.stream() .flatMap( item -> item.stream() ) .forEach(System.out::print); }
@Test public void test4() { List<User> userList = User.getUserList(); userList.stream() .flatMap( user -> user.getHobby().stream() ) .forEach(System.out::print); }
}
|
排序
| 流方法 | 含义 |
|---|
| sorted() | 自然排序,返回自然排序后的流 |
| sorted(Comparator com) | 定制排序,返回按比较器排序后的流 |
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
| public class Demo {
@Test public void test1() { List<Integer> list = Arrays.asList(3, 1, 4, 2, 5); list.stream().sorted().forEach(System.out::print); }
@Test public void test2() { List<User> userList = User.getUserList(); userList.stream() .sorted((a, b) -> Integer.compare(a.getAge(), b.getAge())) .forEach(System.out::println); }
}
|
Stream流终止操作
终止操作简介
(1)终止操作的执行,才会真正开始流的中间操作,会从流的中间操作链生成结果,其结果可以是任何不是流的值
(2)Stream流执行完终端操作之后,无法再执行其他动作,否则会报状态异常,提示该流已经被执行操作或者被关闭,想要再次执行操作必须重新创建Stream流
(3)一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。
匹配与查找
| 流方法 | 含义 |
|---|
| allMatch(Predicate p) | 检查是否匹配所有元素 |
| anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
| noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
| findFirst() | 返回第一个元素 |
| findAny() | 返回当前流中的任意元素 |
| count() | 返回流中元素总数 |
| sum(Comparator c) | 求和,与maptoint中间操作结合使用 |
| max(Comparator c) | 返回流中最大值 |
| min(Comparator c) | 返回流中最小值 |
| forEach(Consumer c) | 遍历流,Stream API内部进行迭代,若使用 Collection 接口需要用户去做迭代, 称为外部迭代。 |
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| public class Demo {
@Test public void test1() { List<User> userList = User.getUserList(); boolean b = userList.stream() .distinct() .allMatch(user -> user.getAge() > 10); System.out.println(b); }
@Test public void test2() { List<User> userList = User.getUserList(); boolean b = userList.stream() .distinct() .anyMatch(user -> user.getName().equals("小明")); System.out.println(b); }
@Test public void test3() { List<User> userList = User.getUserList(); boolean b = userList.stream() .distinct() .noneMatch(user -> user.getName().equals("小明")); System.out.println(b); }
@Test public void test4() { List<User> userList = User.getUserList(); Optional<User> first = userList.stream() .distinct() .findFirst(); System.out.println(first); }
@Test public void test5() { List<User> userList = User.getUserList(); Optional<User> any = userList.parallelStream() .distinct() .findAny(); System.out.println(any); }
@Test public void test6() { List<User> userList = User.getUserList(); long count = userList.parallelStream() .distinct() .count(); System.out.println(count); }
@Test public void test7() { List<User> userList = User.getUserList(); int sum = userList.parallelStream() .mapToInt(User::getId) .sum(); System.out.println(sum); }
@Test public void test8() { List<User> userList = User.getUserList(); OptionalInt max = userList.parallelStream() .mapToInt(User::getId) .max(); System.out.println(max); }
@Test public void test9() { List<User> userList = User.getUserList(); OptionalInt max = userList.parallelStream() .mapToInt(User::getId) .min(); System.out.println(max); }
@Test public void test10() { List<User> userList = User.getUserList(); userList.parallelStream() .mapToInt(User::getId) .forEach(System.out::println); }
}
|
规约
| 流方法 | 含义 |
|---|
| reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 T |
| reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 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 30
| public class Demo {
@Test public void test1() { List<Integer> list = Arrays.asList(1, 2, 3, 3); Integer reduce = list.stream() .distinct() .reduce(5, Integer::sum);
System.out.println(reduce); }
@Test public void test2() { List<User> userList = User.getUserList(); OptionalInt reduce = userList.stream() .mapToInt(User::getAge) .reduce((a1, a2) -> a1 + a2); System.out.println(reduce); }
}
|
汇总
| 流方法 | 含义 |
|---|
| collect(Collector c) | 收集器,把Stream流操作后的结果数据转换为其他形式(集合、数组) 接收一个 Collector 接口的实现,用于给Stream中元素做汇总的方法 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Demo {
@Test public void test() { List<User> userList = User.getUserList(); List<String> collect = userList.stream() .distinct() .map(user -> user.getName()) .collect(Collectors.toList()); System.out.println(collect); }
}
|
Collector收集策略接口
(1)Collector接口是结果收集策略的核心接口,具备将指定元素累加存放到结果容器中的能力
(2)在Collectors工具中提供了Collector接口的实现类,可以方便地创建常见收集器实例
| 方法 | 作用 |
|---|
| toList | 把流中元素收集到List |
| toSet | 把流中元素收集到Set |
| toMap | 把流中元素收集到Map |
| toCollection | 把流中元素收集到创建的集合 |
| counting | 计算流中元素的个数 |
| summingInt | 对流中元素的整数属性求和 |
| averagingInt | 计算流中元素Integer属性的平均值 |
| summarizingInt | 收集流中Integer属性的统计值,平均值 |
| joining | 连接流中每个字符串 |
| maxBy | 根据比较器选择最大值 |
| minBy | 根据比较器选择最小值 |
| reducing | 从一个作为累加器的初始值开始, 利用BinaryOperator与流中元素逐个结合从而归约成单个值 |
| collectingAndThen | 包裹另一个收集器,对其结果转 换函数 |
| partitioningBy | 根据某属性值对流分组 属性为K, 结果为V |
| partitioningBy | 根据true或false进行分区 |
Optional类(Java8)
Optional类简介
(1)为了解决空指针异常,Google公司著名的Guava项目引入了Optional类, Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。
(2)受到Google Guava的启发,Optional类已经成为Java 8类库的一部分
(3)Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在,或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念,并且可以避免空指针异常
(4)Optional提供很多有用的方法,这样我们就不用显式进行空值检测
创建Optional类对象的方法
| 方法 | 简介 |
|---|
| Optional.of(T t) | 创建一个 Optional 实例,t必须非空; |
| Optional.empty() | 创建一个空的 Optional 实例 |
| Optional.ofNullable(T t) | t可以为null |
判断Optional容器中是否包含对象
| 方法 | 简介 |
|---|
| boolean isPresent() | 判断是否包含对象 |
| void ifPresent(Consumer consumer) | 如果有值,就执行Consumer 接口的实现代码,并且该值会作为参数传给它。 |
获取Optional容器的对象
| 方法 | 简介 |
|---|
| T get() | 如果调用对象包含值,返回该值,否则抛异常 |
| T orElse(T other) | 如果有值则将其返回,否则返回指定的other对象。 |
| T orElseGet(Supplier other) | 如果有值则将其返回,否则返回由 Supplier接口实现提供的对象。 |
| T orElseThrow(Supplier exceptionSupplier) | 如果有值则将其返 回,否则抛出由Supplier接口实现提供的异常。 |