JDK8特性-lambda表达式
参考文献
- Java攻略:Java常见问题的简单解法
- Java8 实战
lambda
表达式
-
函数式接口:是一种包含单一抽象方法(
single abstract method
)的接口.类通过为接口中的所有方法提供实现来实现任何接口,这可以通过顶级类(top-level class
),内部类甚至匿名内部类完成. -
lambda
表达式必须匹配接口中单一方法签名的参数类型和返回类型,这被称为与方法签名兼容.因此lambda
表达式属于接口方法的实现,可以将其赋值给该接口类型的引用.- Java库中不存在名为
lambda
的类,lambda
表达式只能被赋值给函数式接口引用.
- Java库中不存在名为
-
lambda
表达式在任何情况下都不能脱离上下文存在,上下文指定了将表达式给哪个函数式接口.lambda
表达式既可以是方法的参数,也可以是方法的返回类型,还可以被赋给引用.- 无论哪种情况,赋值类型必须为函数式接口.
-
lambda
表达式的本质就是匿名函数,在定义和调用时不需要被赋予类型名或绑定到标识符.
方法引用
-
使用**双冒号表示法(::)**将示例引用或类名与方法分开.
-
语法
object::instanceMethod
: 引用特定对象的实例方法.如System.out::println
Class::staticMethod
: 引用静态方法,如Math::max
Class::instanceMethod
: 调用特定类型的任意对象的实例方法,如String::length
构造函数引用
- 在方法中使用
new
关键字
1 | List<String> names = Arrays.asList("A","B","C"); |
Person::new
的作用是引用Person类的构造函数.与所有lambda
表达式类似,有上下文决定执行哪个构造函数.由于上下文提供一个字符串,则使用单参数的String构造函数.
复制构造函数
-
复制构造函数(copy constructor)传入一个Person参数,并返回一个具有相同特性的新Person.
1
2
3public Person(Person p){
this.name = p.name;
}1
final List<Person> people = Stream.of(before).map(Person::new).collect(Collectors.toList());
- 若需要将流代码从原始实例中分离出来,复制构造函数将很有用.
可变参数构造函数
1 | public Person(String... names){ |
1 | names.stream() |
数组
-
构造函数引用也可以和数组一起使用.若希望采用实例的数组(Person[])而非列表,可以使用Stream接口定义的toArray方法
1
<A> A[] toArray(IntFunction<A[]> generator)
- toArray方法采用A表示返回数组的泛型类型(generic type).数组包含流的元素,由所提供的generator函数创建.
1
2
3Person[] people = names.stream()
.map(Person::new)
.toArray(Person::new);
异常处理
-
任何函数式结构都不允许抛出受检异常(
checked exception
) -
若需要kanbda表达式抛出异常,有两种办法
-
定一个自己的函数式接口,并声明受检异常
1
2
3
4
5
public interface BufferReaderProcessor {
String process(BufferedReader b) throws IOException;
}
BufferReaderProcessor p = (BufferedReader br) -> br.readLine(); -
或者把
lambda
包在一个try-catch
块中1
2
3
4
5
6
7Function<BufferedReader,String> f = (BufferedReader b) -> {
try{
return b.readLine();
} catch(IOExecption e){
throws new RuntimeException();
}
}
-
函数式接口
- 创建只包含单一抽象方法的接口,并为其添加
@FunctionalInterface
注解.
java.util.function
包
java.util.function
包中接口分为四类Consumer
消费型接口Supplier
供给型(生产者)接口Predicate
谓词型接口Function
功能型接口
函数式接口 | 方法名称 | 参数 | 返回值 |
---|---|---|---|
Runnable |
run |
无参数 | 无返回值 |
Function |
apply |
1个参数 | 有返回值 |
Consumer |
accept |
1个参数 | 无返回值 |
Supplier |
get |
无参数 | 有返回值 |
BiConsumer |
accept |
2个参数 | 无返回值 |
函数式接口 | 函数描述符 | 原始类型特化 |
---|---|---|
Predicate<T> |
T->boolean |
IntPredicate,DoublePredicate,LongPredicate |
Consumer<T> |
T->void |
IntConsumer,DoubleConsumer,LongConsumer |
Function<T, R> |
T->R |
IntFunction<R>,IntToDoubleFunction,IntToLongFunction, DoubleFunction<R> ,LongFunction<R>,LongToDoubleFunction,LongToIntFunction ToIntFunction<T>,ToDoubleFunction<T>,ToLongFunction<T> |
Supplier<T> |
()->T |
BooleanSupplier,IntSupplier,DoubleSupplier,LongSupplier |
UnaryOperator<T> |
T->T |
IntUnaryOperator,LongUnaryOperator,DoubleUnaryOperator |
BinaryOperator<T> |
(T,T)->T |
IntBinaryOperator,DoubleBinaryOperator,LongBinaryOperator |
BiPredicate<T, U> |
(T,U)->boolean |
|
BiConsumer<T, U> |
(T,U)->void |
ObjIntConsumer<T>,ObjDoubleConsumer<T> ,ObjLongConsumer<T> |
BiFunction<T, U, R> |
(T,U)->R |
ToIntFunction<T>,ToDoubleFunction<T>,ToLongFunction<T> |
java.util.function.Consumer
接口
1 | package java.util.function; |
java.util.function.Supplier
接口
1 | package java.util.function; |
java.util.function.Predicate
接口
Predicate
接口主要用于流的筛选.
1 | package java.util.function; |
java.util.function.Function
接口
Function
接口包含的单一抽象方法为apply
,它可以将T类型的泛型输入参数转换为R类型的泛型输出值.
1 | package java.util.function; |
Optional
Optional
是用于防范NullPointerException
创建Optional
对象
声明一个空的Optional
1 | final Optional<Object> empty = Optional.empty(); |
依据一个非空值创建Optional
1 | final Optional<Person> person = Optional.of(test); |
可接受null
的Optional
1 | final Optional<Person> test = Optional.ofNullable(person); |
使用Optional
对象
使用map
从Optional
对象中提取和转换值
1 | final Optional<String> name = test.map(Person::getName); |
1 | final Optional<Employee> department = Optional.of(new Employee()); |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!