前言

Java8 有一个非常显著的特点,就是提供了函数式编程,本文也将介绍 Java8 的几个新特性来实现函数式编程。学会这些 API 能够编写出简单、干净、易读的代码(尤其是对集合的操作)。Java8 新特性包括:

  • Lambda 表达式
  • Stream API
  • 接口新特性
    • 函数式接口(@FunctionalInterface
    • 默认方法(default
  • Optional API
  • 方法引用

JDK8 新特性

正在努力更新中…

函数式接口

  • 只包含了一个抽象方法的接口,称为函数式接口(可以有多个非抽象方法)。可以使用@FunctionalInterface注解自定义声明
1
2
3
4
5
6
7
8
9
10
11
12
13
//JDK 1.8 之前已有的函数式接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
//JDK 1.8 新增加的函数接口:
- java.util.function

Lambda 表达式

  • Lambda表达式的使用依赖于函数式接口
  • 使用Lambda表达式来表示函数式接口的实现(JAVA 8 之前一般是用匿名类实现的)

语法格式

  • -> :Lambda操作符
  • -> 左边(parameters):Lambda形参列表(相当于接口中的抽象方法的形参列表)
  1. 参数类型可以省略,可由编译器推断得出(类型推断)
  2. 如果只有一个参数,()也可以省略
  • -> 右边:Lambda体(重写的抽象方法的方法体)
  1. 如果只有一条执行语句,{}return可以省略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(parameters) -> expression

(parameters) ->{ statements; }
// 1. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 2. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

@Test
public void test(){
Runnable runnable=new Runnable(){
@Override
public void run(){
System.out.println("*********");
}
}
runnable.run();
//Lambda表达式写法
Runnable runnable= () -> System.out.println("*********");
runnable.run();
}

使用案例

使用案例 Lambda 的例子 对应的函数式接口
布尔表达式 (List<String> list) -> list.isEmpty() Predicate<List<String>>
创建对象 () -> new Project() Supplier<Project>
消费一个对象 (Project p) -> System.out.println(p.getStars()) Consumer<Project>
从一个对象中选择/提取 (int a, int b) -> a * b IntBinaryOperator
比较两个对象 (Project p1, Project p2) -> p1.getStars().compareTo(p2.getStars()) Comparator<Project> 或 BiFunction<Project, Project, Integer> 或 ToIntBiFunction<Project, Project>

方法引用

语法格式

  • 使用操作符::类或对象与方法名分割
  • 主要有三种使用情况

对象::实例方法名

::实例方法名

::静态方法名

使用案例

1
2
3
4
LambdaQueryWrapper<SysDictItem> queryWrapper = new LambdaQueryWrapper<SysDictItem>();
//相当于SysDictItem.getStatus();
queryWrapper.eq(SysDictItem::getStatus, 1);
queryWrapper.orderByAsc(SysDictItem::getSortOrder);

Stream API

  • 使用Stream API对集合数据进行操作
  • streamcollection 集合的区别
    • collection是一种静态的内存数据结构,而stream是有关计算的,前者主要面向内存,存储在内存中,后者主要面向cpu,通过cpu计算实现
  • Stream的创建方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.通过集合创建
//default Stream<E> stream();//返回一个顺序流
//default Stream<E> parallelStream();//返回一个并行流
List<Person> list = new ArrayList<Person>();
Stream<Person> stream = list.stream();

//2.通过Arrays静态方法
String[] names = {"chaimm","peter","john"};
Stream<String> stream = Arrays.stream(names);

//3.通过Stream of
Stream<String> stream = Stream.of("chaimm","peter","john");

//4.创建无限流
//迭代 遍历0到9
Stream.iterate(0,t->t+1).limit(10).forEach(System.out::println);
//生成 10个随机数
Stream.generate(Math::random).limit(10).forEach(System.out::println);
  • 中间操作
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
//中间操作
//filer(Predicate p)过滤数据
List<Person> result = list.stream()
.filter(Person::isStudent)
.collect(toList());

//limit(n)截断流
List<Person> result = list.stream()
.limit(3)
.collect(toList());

//skip(n)跳过元素
List<Person> result = list.stream()
.skip(3)
.collect(toList());

//distinct 筛选去重
List<Person> result = list.stream()
.distinct()
.collect(toList());

//映射map(Function f) flatMap(Function f)合并多个流
List<String> result = list.stream()
.map(Person::getName)
.collect(toList());

//排序 sorted() 自然排序 sorted(Comparator c)定制顺序
  • 终止操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 //终止操作
//匹配与查找
//allMatch(Predicate e)检查是否匹配所有元素 返回boolean
boolean result = list.stream()
.allMatch(Person::isStudent);
//anyMatch(Predicate e)检查是否至少匹配一个元素
boolean result = list.stream()
.anyMatch(Person::isStudent);
//noneMatch(Predicate e)检查是否没有匹配的元素
boolean result = list.stream()
.noneMatch(Person::isStudent);
//findFierst()返回第一个元素
Optional<Person> person = list.stream().findFirst();
//findAny()返回当前流中的任意元素
Optional<Person> person = list.stream().findAny();
//count 返回流中元素的总个数
//max(Comparator c)返回流中最大值
//min(Comparator c)返回流中最小值
//forEach(Consumer c)内部迭代
//归约 reduce(T identity,BinaryOperator)可以将流中元素结合起来得到一个值(求和)
//例:计算所有人的年龄总和
int age = list.stream().reduce(0, (person1,person2)->person1.getAge()+person2.getAge());
//收集collect(Collector c) 将流中元素收集返回相应类型

中间操作和收集操作

操作 类型 返回类型 使用的类型/函数式接口 函数描述符
filter 中间 Stream<T> Predicate<T> T -> boolean
distinct 中间 Stream<T>
skip 中间 Stream<T> long
map 中间 Stream<R> Function<T, R> T -> R
flatMap 中间 Stream<R> Function<T,Stream<R>> T -> Stream<R>
limit 中间 Stream<T> long
sorted 中间 Stream<T> Comparator<T> (T, T) -> int
anyMatch 终端 boolean Predicate<T> T -> boolean
noneMatch 终端 boolean Predicate<T> T -> boolean
allMatch 终端 boolean Predicate<T> T -> boolean
findAny 终端 Optional<T>
findFirst 终端 Optional<T>
forEach 终端 void Consumer<T> T -> void
collect 终端 R Collector<T, A, R>
reduce 终端 Optional<T> BinaryOperator<T> (T, T) -> T
count 终端 long

新的日期和 API

参考:hellokaton/learn-java8