java 8 总结 之lambda
来源:互联网 发布:苹果音频编辑软件 编辑:程序博客网 时间:2024/06/09 16:32
lambda表达式
目的:行为参数化
Lambda表达式是简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
Lambda的基本语法是(parameters) -> expression
或 (parameters) -> { statements; }
。其中,(parameters) -> expression
的表达式中隐含了return,如 () -> 42
; (parameters) -> { statements; }
的花括号内是语句。
举例:
() -> 42 //参数为空,返回一个int(List<String> list) -> list.isEmpty() //参数为list,返回一个boolean(int x, int y) -> x*y //参数为两个int,返回一个int(String s) -> System.out.println(s); //参数为一个String,不返回结果(String s) -> {System.out.println(s);} //参数为一个String,打印字符串
哪些地方使用哪些lambda
函数式接口是只定义一个抽象方法的接口,即使拥有多个默认方法。FunctionalInterface 标注一个函数式接口,会加入编译检查。函数式接口中默认方法的目的是:改变已发布的接口而不破坏已有的实现。
在接受函数式接口为参数的地方,都可以使用lambda表达式。
栗子:
public void execute(Runnable r){ r.run(); }execute(() -> {}); //使用lambda,Runnable是参数为空,没有返回值的函数式接口,即() -> void //fetch返回一个函数式接口,() -> Stringpublic Callable<String> fetch() { return () -> "Tricky example ;-)";}
喵:为什么只有在函数式接口的地方使用呢?lambda表达式没有函数名,只有参数列表,函数主体和返回值,如果接口有多个方法,就不能直接匹配到正确的方法上了,所以,只有一个抽象方法的函数式接口可以满足。
Predicate
java.util.function.Predicate<T>
是一个含有多个默认方法的函数式接口,抽象方法为:(T t) -> bool
。看下代码,你就懂了~
FunctionalInterfacepublic interface Predicate<T> { //接口方法,入参为泛型T,返回bool。即:(T t) -> bool boolean test(T t); //默认方法,and操作 default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } //默认方法,取反操作 default Predicate<T> negate() { return (t) -> !test(t); } //默认方法,or 操作 default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } //默认方法,判断是否相等 static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
使用
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
Consumer
java.util.function.Consumer<T>
是一个只含有一个默认方法的函数式接口,抽象方法为:(T t) ->void
。看下代码,你就懂了~
@FunctionalInterfacepublic interface Consumer<T> { //接口方法,入参为泛型T,返回void。即:(T t) -> void void accept(T t); //默认方法,可以执行级联操作 default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }
Function
java.util.function.Function<T, R>
是一个含有多个默认方法的函数式接口,抽象方法为:(T t) ->R
。看下代码,你就懂了~
@FunctionalInterfacepublic interface Function<T, R> { //接口方法,入参为泛型T,返回泛型R。即:(T t) -> R R apply(T t); //默认方法,实现级联操作。before方法输入V,输出T,本function输入T,输出R。 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } //默认方法,级联操作 default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } //默认方法,输入啥,输出啥 static <T> Function<T, T> identity() { return t -> t; }
特定方法避免装箱操作
在处理数据时,使用特定方法,可以避免装箱操作,如:IntPredicate、LongConsumer、DoubleFunction等。具体见API库。
总结
java.util.function.Predicate<T>
(T) -> voidjava.util.function.Consumer<T>
(T) -> Rjava.util.function.Function<T, R>
(T,U) -> Rjava.util.function.BiFunction<T, U, R>
() -> Tjava.util.function.Supplier<T>
只要函数描述符兼容,函数式接口就可以复用。
特殊的void兼容规则:
// Predicate返回了一个boolean Predicate<String> p = s -> list.add(s); // Consumer返回了一个void Consumer<String> b = s -> list.add(s);
方法引用
方法引用是调用单一方法的Lambda的快捷写法,格式ClassName::methodName
。看下栗子你就懂了~
一般方法引用
(Apple a) -> a.getWeight() 等价于Apple::getWeight () -> Thread.currentThread().dumpStack() 等价于 Thread.currentThread()::dumpStack(str, i) -> str.substring(i) 等价于 String::substring(String s) -> System.out.println(s) 等价于 System.out::println(list, element) -> list.contains(element) 等价于 List::contains
主要有三类:
- 指向静态方法的方法引用,如:Integer::parseInt
- 指向任意类型实例方法的方法引用,如:String::length
- 指向现有对象的实例方法的方法引用,如:User::getUserId
构造函数引用
- 无参构造函数
无参构造函数的函数描述符:() -> T
,由上面的总结知,可以使用Supplier接口,如下:
Supplier<User> c1 = User::new; // c1 = () -> new User();User user = c1.get();
- 有一个参数的构造函数
有一个参数的构造函数的函数描述符是(T) -> R
,可以使用Function接口,如下:
Function<Long, User> c2 = User::new;User user = c2.apply(110L);
- 有三个参数的构造函数
有三个参数的构造函数的函数描述符是(T,U,V) -> R
,没有现成的接口,需要自定义,如下:
@Data@AllArgsConstructorpublic class User { private String name; private Long userId; private Integer age;}@FunctionalInterfacepublic interface TriFunction<T,U,V,R> { R create(T t, U u, V v);}public static void main(String[] args) { TriFunction<String, Long, Integer, User> triFunction = User::new; User user = triFunction.create("tina", 12L, 13);}
使用注意事项
- Lambda表达式可以引用静态变量、成员变量和最终的(final) 或事实上最终的局部变量。
- java 8 总结 之lambda
- java 8 总结 之lambda
- Java 8之Lambda
- Java 8 之Lambda表达式
- Java 8之Lambda表达式
- Java 8 之Lambda表达式
- java8之lambda总结
- Java 8 Lambda 表达式学习心得总结
- java 8 lambda 表达式的优缺点总结
- Java 8 新特性之 Lambda 表达式
- java 8之Lambda Expressions 解说
- Java 8 新特性之 Lambda表达式
- Java 8特性探究(1)之lambda
- Java 8系列之Lambda表达式
- Java 8学习之Lambda表达式
- java之Lambda表达式
- Java之lambda表达式
- JAVA之Lambda表达式
- [bzoj4543] [POI2014]Hotel加强版
- 寻找最大数(三)
- 领域驱动设计,读书笔记:6 DDD+面向对象中的基本构造块
- BFS:题目1456:胜利大逃亡
- 嵌入式Linux驱动笔记(十三)------spi设备之RFID-rc522驱动
- java 8 总结 之lambda
- 1082: 敲7(多实例测试)
- 记录一个自己用的添加excel内容的类
- ArcEngine数据删除几种方法和性能比较
- Power OJ 魔术球问题
- 【POJ1201】Intervals-差分约束系统+单源最长路
- python3.6+pyqt5实现GUI设计(二)
- 商城项目-dubbo,框架整合,dubbo发布和引用服务
- Eclipse4.7创建Maven项目报错解决方法