1.函数式接口
/**
* 函数式接口:
* 1)接口中可以有多个方法,但抽象方法只能有一个
* 2)一般使用@FunctionalInterface标记
* 3)lambda表达式的前提就是函数式接口,lambda表达式抛出的异常必须和抽象方法声明的throws语句匹配
*/
@FunctionalInterface
public interface PeoplePredicate {
/**
* 谓词,返回一个boolean值的函数
*/
boolean test(People people);
}
2.lambda表达式demo
/**
* lambda表达式: (参数列表)-> 返回值
*/
public class Fun8Main {
public static void main(String[] args) {
List<People> peoples = new ArrayList<> ();
peoples.add(People.builder().name("zs").sex((byte) 1).weight(80).height((byte) 183).address("XiAn").build());
peoples.add(People.builder().name("ls").sex((byte) 0).weight(48).height((byte) 160).address("ChongQing").build());
peoples.add(People.builder().name("ws").sex((byte) 0).weight(51).height((byte) 168).address("ShangHai").build());
peoples.add(People.builder().name("zl").sex((byte) 1).weight(75).height((byte) 176).address("BeiJing").build());
peoples.add(People.builder().name("zq").sex((byte) 0).weight(53.5f).height((byte) 170).address("XiaMen").build());
//第一步简化:匿名类
List<People> filterPeople01 = filterPeopleSex(peoples, new PeoplePredicate() {
@Override
public boolean test(People people) {
return people.getSex() == 1;
}
});
//第二步简化:lambda表达式
List<People> filterPeople02 = filterPeopleSex(peoples, p -> p.getSex() == 1);
filterPeople02.forEach(System.out::println);
}
//行为参数化,使用接口传递操作行为
public static List<People> filterPeopleSex(List<People> peoples, PeoplePredicate predicate){
List<People> filterPeoples = new ArrayList<>();
for(People p: peoples){
if(predicate.test(p)) {
filterPeoples.add(p);
}
}
return filterPeoples;
}
}
3.Java8常见的函数式接口及变种:主要限制了参数列表和返回值的类型
-
Predicate<T>, T -> boolean
-
IntPredicate, int -> boolean
-
LongPredicate, long -> boolean
-
DoublePredicate, double -> boolean
-
-
Consumer<T>, T -> void
-
IntConsumer, int -> void
-
LongConsumer, long -> void
-
DoubleConsumer, double -> void
-
-
Function<T,R>, T -> R
-
IntFunction<R>, int -> R
-
IntToDoubleFunction, int -> double
-
IntToLongFunction, int -> long
-
LongFunction<R>, long -> R
-
LongToDoubleFunction, long -> double
-
LongToIntFunction, long -> Int
-
DoubleFunction<R>, double -> R
-
ToIntFunction<T>, T -> int
-
ToDoubleFunction<T>, T -> double
-
ToLongFunction<T>, T -> long
-
-
Supplier<T>, () -> T
-
BooleanSupplier, () -> boolean
-
IntSupplier, () -> int
-
LongSupplier, () -> long
-
DoubleSupplier, () -> double
-
-
UnaryOperator<T>, T -> T
-
IntUnaryOperator, int -> int
-
LongUnaryOperator, long -> long
-
DoubleUnaryOperator, double -> double
-
-
BiPredicate<L,R>, (L,R) -> boolean
-
BiConsumer<T,U>, (T,U) -> void
-
ObjIntConsumer<T>, (T,int) -> void
-
ObiLongConsumer<T>, (T,long) -> void
-
ObjDoubleConsumer<T>, (T,double) -> void
-
-
BiFunction<T,U,R>, (T,U) -> R
-
ToIntBitFunction<T,U>, (T,U) -> Int
-
ToLongBiFuncation<T,U>, (T,U) -> long
-
ToDoubleBiFunction<T,U>, (T,U) -> double
-
-
BinaryOperator<T>, (T,T) -> T
-
IntBinaryOperator, (int, int) -> int
-
LongBinaryOperator, (long, long) -> long
-
DoubleBinaryOperator, (double, double) -> double
-
4.方法引用
- 在函数式接口的基础上的某些特殊场景下,对一些现有方法的调用来完成接口抽象方法的具体实现
-
常见类型
-
对象::实例方法名
-
类名::静态方法
-
类名::实例方法,参数列表的第一个参数调用实例方法
-
类型::new,返回一个实例,参数列表必须和构造器参数列表匹配
-
-
代码demo
public class MethonReference {
public static void main(String[] args) {
//实例方法,对象::方法名
FunImpl funImpl = new FunImpl();
stringOps("hello", s -> funImpl.str2Upper(s));
String str1 = stringOps("hello", funImpl :: str2Upper);
System.out.println(str1);
//静态方法,类名::方法名
stringOps(2, i -> String.valueOf(i));
String str2 = stringOps(2, String::valueOf);
System.out.println(str2);
//参数列表的第一个参数是实例方法的调用者,类名::方法名
stringOps("hello", s -> s.length());
Integer num = stringOps("hello", String::length);
System.out.println(num);
//构造器,此类必须有一个和参数列表匹配的构造方法
stringOps("独孤求败", s -> new People(s));
People p = stringOps("独孤求败", People :: new);
System.out.println(p);
}
static class FunImpl{
public String str2Upper(String s){
return s.toUpperCase();
}
}
public static <T, R> R stringOps(T t, Function<T, R> fun) {
return fun.apply(t);
}
}