什么是函数式接口
所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。(一个抽象方法、单一抽象方法接口)需要注意的是接口的默认方法和静态方法并不影响一个接口成为函数式接口。
@FunctionlInterface注解
Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
注意:函数式接口允许定义静态方法、默认方法、Object中的方法
JDK8之前,接口中可以定义变量和方法,变量必须是public 、static、final的方法必须是public 、 abstract的JDK8后,允许在接口中定义static方法和default方法
public interface JDK8BeforeInteface {
static void staticMethod(){
System
.out
.println("接口中的静态方法");
}
default void defaultMethod(){
System
.out
.println("接口中的默认方法");
}
如果有两个接口的静态方法一模一样,并且一个实现类同时实现了这两个接口,此时并不会报错,因为JDK8只能通过接口类调用接口中的静态方法所有对编译器来说是可以区分的。但是如果两个接口中定义了一模一样的默认方法的时候,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译报错。
public class JDK8BeforeIntefaceImpl implements JDK8BeforeInteface,JDK8BeforeInteface2
{
@Override
public void defaultMethod() {
System
.out
.println("接口实现类覆盖了接口中的default");
}
JDK中的函数式接口
JDK1.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 它包含了很多的类,用支持Java的函数编程。
除了早期存在的Runnable,Comparator等函数式接口之外,jdk8中又增加了java.util.function包,
其中提供了常用的函数式接口,比如:
1.Predicate
2.Function
3.Consumer
4.Supplier
Lambda表达式概述
lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包:
java.util.function 包以及java.util.stream 包。流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。Lambda表达式的类型叫做"目标类型",它是一个函数接口(定义:一个接口,如果只有一个显示声明的抽象方法,那么它就是一个函数接口。一般用@FunctionlInterface)
Lambda表达式语法格式:
基本语法:
(parameters) -> expression
或
(parameters) -> {statements;}
三部分构成
参数列表
符号 ->
函数体 : 有多个语句,可以用{} 包括, 如果需要返回值且只有一个语句,可以省略 return
@FunctionalInterface
interface FunctionInterface{
void operation(String str
);
}
public static void main(String
[] args
) {
FunctionInterface fi
= (String s
) -> System
.out
.println(s
);
fi
.operation("你好Lambda");
}
Lambda表达式
无参数,无返回值有参数,无返回值有参数,有返回值
Lambdas和Streams
Stream是对集合的包装,通常和lambda一起使用。使用lambdas可以支持许多操作,如map,filter,limit,count,min,max,sum,collect等等重点:
forEach、forEachRemaining
public static void main(String
[] args
) {
Collection
<String> c
= new HashSet<>();
c
.add("123");
c
.add("456");
c
.add("789");
for (String string
: c
) {
System
.out
.println(string
);
}
c
.forEach(new Consumer<String>() {
@Override
public void accept(String t
) {
System
.out
.println("集合元素:"+t
);
}
});
c
.forEach(t
-> System
.out
.println("迭代集合元素:"+t
));
c
.forEach(System
.out
::println
);
}
JDK8还新增了forEachRemaining(Consumer action)方法,该方法所需要的Consumer参数同样是函数式接口。当程序调用Iterator的forEachRemaining(Consumer action)遍历集合元素。程序会一次将集合元素传递给Consumer的accept(T t)方法(该接口中唯一的抽象方法)
public static void main(String
[] args
) {
Collection
<String> c
= new HashSet<>();
c
.add("西门庆");
c
.add("武大郎");
c
.add("小潘");
Iterator
<String> iterator
= c
.iterator();
iterator
.forEachRemaining(System
.out
::println
);
}