函数式接口

首先它是一个接口,有且只有一个抽象方法
接口上使用注解 @FunctionalInterface 进行声明,这个注解是非必须的,该注解是提醒编译器去检查该接口是否仅包含一个抽象方法

  • 函数式接口里是可以包含默认方法,因为默认方法不是抽象方法
  • 函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法
1
2
3
4
@FunctionalInterface
public interface funcInterfaceDemo {
public abstract void hello();
}

Lambda表达式

我们能够使用 Lambda 实例化函数式接口
Lambda表达式由三个部分组成:第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。
若方法体为代码块,必须用 {} 来包裹起来。

要使用 Lambda 表达式,需要定义一个函数式接口,这样会让程序充斥着过量的仅为 Lambda 表达式服务的函数式接口。为了减少这样过量的函数式接口,Java 8 在 java.util.function 中增加了不少新的函数式通用接口。

  • Function<T, R>:将 T 作为输入,返回 R 作为输出
  • Predicate :将 T 作为输入,返回一个布尔值作为输出
  • Consumer :将 T 作为输入,不返回任何内容
1
2
3
Function<Integer, String> f = (t)->String.valueOf(t);
String fString = f.apply(5);
System.out.println(fString);

forEach方法

使用forEach方法遍历List和Map

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String args[]) {
List<String> rlList = Arrays.asList("1","2");
rlList.forEach(t->{
System.out.println(t);
});

Map<String, String> items = new HashMap<>();
items.put("1", "A");
items.put("2", "B");
items.forEach((k,v)->{
System.out.println(k + v);
});
}

接口的增强

在接口中可以添加使用 default 关键字修饰的非抽象方法,还可以在接口中定义静态方法。

流式操作(Stream)

通过Stream可以实现对集合(Collection)的并行处理和函数式操作。根据操作返回的结果不同,流式操作分为中间操作和最终操作两种。最终操作返回一特定类型的结果,而中间操作返回流本身,这样就可以将多个操作依次串联起来。根据流的并发性,流又可以分为串行和并行两种。流式操作实现了集合的过滤、排序、映射等功能。

Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。

通过 stream.sequential() 返回串行的流,通过 stream.parallel() 返回并行的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。

中间操作

  • filter():对元素进行过滤;
  • sorted():对元素排序;
  • map():元素的映射;
  • distinct():去除重复元素;
  • subStream():获取子 Stream 等。

sorted()排序

1
2
3
4
5
6
7
8
9
List<Integer> rlList = Arrays.asList(1,6,4,2,7,9,3);
rlList.forEach(t->{
System.out.print(t);
});

rlList = rlList.stream().parallel().sorted().collect(Collectors.toList());
rlList.forEach(t->{
System.out.print(t);
});

最终操作

  • forEach():对每个元素做处理;
  • toArray():把元素导出到数组;
  • findFirst():返回第一个匹配的元素;
  • anyMatch():是否有匹配的元素等。