Java 8 在语言层面引入Lambda表达式,用以支持函数式编程风格。Lambda表达式使用五行代码转换为单个语句来解决匿名内部类的庞大性。 这个简单的水平解决方案解决了内部类提出的“垂直问题”。本文对lambda的介绍分为三个方面,语法、常规使用和综合应用三个部分。
1.语法(参数类型 参数名称) ‐> { 代码语句 }:参数非必须,大括号非必须(对于返回值问题,没有大括号的时候表达式的执行结果就是返回值,有大括号的时候需要return 返回结果。)
Argument List Arrow Token Body
一些参数 一个箭头 一段代码
2.常规使用
Java 8 在引入Lambda表达式的同时也引入了一个新的包java.util.function,它包含Function,Predicate,Consumer,Supplier等。从某种程度上说这几个包应该是Lambda表达式最具代表性的应用。
1.Function:功能型接口,用于接收参数然后返回结果 R apply(T t);
2.Predicate:断言式接口,用于评估参数是否满足条件 boolean test(T t);
3.Consumer:消费型接口,接收一个简单的输入但是不会有返回值,可能会有副作用(实际就是对引用类型进行处理)需要实现void accept(T t);
4.Supplier: 供给型接口,提供一个结果,不需要参数,调用后提供一个新的或者截然不同的结果。需要实现T get();
除了这四个之外还有很多针对特定类型的定义,我们先上一段源码,然后再看看这几个接口的特点。
public class TestLambda {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 1. 功能性函数:接收固定参数,处理后返回一个结果
Function<Integer, Integer> function = a -> {
return a * a;
};
System.out.println("功能型接口 :" + function.apply(6));
// 供给型接口,接口不需要参数,调用会提供一个结果
Supplier<String> supplier = () -> {
return "Supplier<String>";
};
System.out.println("供给型接口 " + supplier.get());
// 断言式接口 判断一个数是否大于0
Predicate<Integer> predicate = a -> {
return a > 0;
};
System.out.println("断言式接口 " + predicate.test(18));
//消费性接口 输出输入的参数 ,接收参数,然后做出相应处理。
Consumer<String> consumer = a -> {
System.out.println("消费性接口 " + a.length() + " " + "Test");
};
consumer.accept("消费性接口");
}
}
总结一下这几个接口的使用特点:
1.@FunctionalInterface声明,接口被@FunctionalInterface声明为修饰函数式接口
2.要求接口中的抽象方法只有一个。
3.接口可以使用default定义默认方法
4.接口可以使用static定义静态方法
5.有一个lambda表达式的实现(Lambda表达式是不能单独使用的,必须依赖于函数式接口)
知道了这些基本特点后我们可以写一个我们自己的函数式接口,并使用lambda表达式实现。
public class TestLambda2 {
public static void main(String[] args) {
/**1.多参数无返回*/
TestFunction tf= (a,b) -> {System.out.println("tf2="+(a+b));} ;//无返回值,需要用大括号标明表达式
TestFunction2 tf2= (a,b) -> a + b ;//没有大括号,表达式结果作为返回值
/**多参数有返回*/
tf.method(1, 2);
System.out.println("tf2="+tf2.method(1, 2));
}
}
/**多参数无返回*/
@FunctionalInterface
interface TestFunction {
void method(int a, int b);
}
/**多参数有返回*/
@FunctionalInterface
interface TestFunction2 {
int method(int a, int b);
}
3.综合应用
综合应用主要介绍在lambda 表达式和thread,lambda 表达式和stream和集合一起使用,使用lambda 可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等,这个代码示例很多。
public class TestLambda3 {
public static void main(String[] args) {
List<String> nums = Arrays.asList("1","2","3");
long a = nums.stream().filter(num -> num != null).count();
System.out.println("nums count ="+a);
}
}
把Stream拿出来看其实是想说明Lambda的另一种用法,将lambda表达式作为参数,具体实现方式就是我们上面提到的function包。Stream.map filter是将function的接口作为参数传递的。如同上面“filter(num -> num != null)”其实“num -> num != null”就是Function的一个实现。看一下源码吧,对于开发人员来说我觉得源码是最容易帮助理解的工具,仔细看一下其实并不是每个地方都可以用lambda表达式的。
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
Stream<T> distinct();
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
Stream<T> peek(Consumer<? super T> action);
Stream<T> limit(long maxSize);
Stream<T> skip(long n);
void forEach(Consumer<? super T> action);
void forEachOrdered(Consumer<? super T> action);
Object[] toArray();
<A> A[] toArray(IntFunction<A[]> generator);
T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
Optional<T> min(Comparator<? super T> comparator);
long count();
boolean anyMatch(Predicate<? super T> predicate);
boolean allMatch(Predicate<? super T> predicate);
boolean noneMatch(Predicate<? super T> predicate);
Optional<T> findFirst();
Optional<T> findAny();
}