随着函数式编程的流程,Java8中也引入了函数式编程风格(Lambda表达式)。Lambda表达式允许我们将行为传递到函数中,其可以替换匿名内部类实现的繁琐的代码。下面就是一个最经典的例子,用普通的匿名内部类一共用了6行代码,使用Lambda表达式只需要1行代码即可。也就是说,Lambda表达式在经常使用内部类情况下,可以大大的减少代码量,还有就是Lambda表达式经常和Stream API一起使用。
// 匿名内部类
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("do something");
}
};
// Lambda表达式
Runnable runnable2 = () -> System.out.println("do something");
(Type1 param1, Type2 param2, ..., TypeN typeN) -> {
statment1;
statment2;
// ......
return statmentM;
}
操作符'->':Lambda操作符,该箭头将Lambda表达式拆分为左右两部分
左侧:参数列表,只有一个参数时可以不写()
右侧:Lambda表达式体,就抽象方法实现区域。只有一行代码时可以不写{},参数类型也可以不用写(Java会通过上下文进行判断)
上面是标准的Lambda表达式,一般情况下Lambda表达式可以分为以下几种类型:
() -> {
statment1;
statment2;
...
statmentN;
}
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
...
statmentN;
}
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
...
statmentN;
return value;
}
下面是一个实现List排序功能(根据字符串长度)的例子,可以看到这个例子是有参有返回值的,但是没有写return值(在单见场景下可以省略不写)
List list = new ArrayList<>();
list.add("my");
list.add("name");
list.add("is");
list.add("super");
list.add("man");
// 非lambda实现排序
Collections.sort(list, new Comparator() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
list.stream().forEach((x)->System.out.println(x));
// lambda实现排序
Collections.sort(list, (o1, o2) -> o2.length() - o1.length());
list.stream().forEach((x)->System.out.println(x));
函数式接口就是一个有且仅有一个抽象方法,但是有多个非抽象方法的接口。Lambda表达式需要函数式接口的支持,下面是自定义的函数式接口:
@FunctionalInterface
public interface TestService {
void test();
}
// 使用代码
TestService testService = ()->System.out.println("test");
testService.test();
@FunctionalInterface注解用于标识该接口是函数式接口,如果不满足函数式接口规则,则编译会报错,当然函数式接口并不一定需要@FunctionalInterface注解。
Java中常用的四个核心函数式接口包括:1、Consumer
@FunctionalInterface
public interface Consumer {
void accept(T t);
default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
主要方法:
accept(T t):接受一个指定类型的参数,但无返回值
andThen(Consumer super T> after):从左向右执行
List list2 = Arrays.asList("a","bb","ccc","dddd","eeeee");
Consumer consumer = (x) -> System.out.println("input:" + x);
list2.stream().forEach(consumer);
@FunctionalInterface
public interface Supplier {
T get();
}
主要方法:
T get():不接受任何参数,但返回执行类型的值
List list1 = new ArrayList<>();
Supplier supplier = () -> (int)(Math.random() * 100);
for (Integer i = 0; i < 10; i++) {
list1.add(supplier.get());
}
list1.stream().forEach((x) -> System.out.println(x));
@FunctionalInterface
public interface Function {
R apply(T t);
default Function compose(Function super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default Function andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static Function identity() {
return t -> t;
}
}
主要方法:
R apply(T t):接受一个指定类型的参数,返回一个执行的结果类型
andThen和compose方法:执行顺序不一样,andThen是从左向右执行;compose是从右向左执行;
Function function1 = (x) -> x.toUpperCase();
List list4 = list2.stream().map(function1).collect(Collectors.toList());
for (String elem : list4) {
System.out.println("String Upper:" + elem);
}
Function function2 = (x) -> x * 3;
Function function3 = (x) -> x + 8;
System.out.println("andThen:" + function2.andThen(function3).apply(1));
System.out.println("compose:" + function2.compose(function3).compose(function3).apply(1));
@FunctionalInterface
public interface Predicate {
boolean test(T t);
default Predicate and(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate negate() {
return (t) -> !test(t);
}
default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static Predicate isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
主要方法:
boolean test(T t):传入指定值用于判断,返回true或者false
and、negate、or、isEqual方法代表与、非、或、相等。