lambda可以隐藏return
简洁的代码
Comparator<Apple> comparator = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
Comparator<Apple> comparator1 = new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
};
常见的函数式接口
函数式接口可以有多个默认方法,但是只能有一个抽象方法。
@FunctionalInterface只是一个标志符号,并不是必须的。就像@Override标注。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
image.png
image.png
任何函数式接口都不允许抛出受检异常( checked exception)。
如果需要Lambda表达式来抛出异常, 有两种办法:
定义一个自己的函数式接口,并声明受检异常,或者把Lambda包在一个try/catch块中。
比如,一个新的函数式接口BufferedReaderProcessor,它显式声明了一个IOException:
@FunctionalInterface
public interface BufferedReaderProcessor {
String process(BufferedReader b) throws IOException;
}
BufferedReaderProcessor p = (BufferedReader br) -> br.readLine();
显式捕捉受检异常:
Function<BufferedReader, String> f = (BufferedReader b) -> {
try {
return b.readLine();
}
catch(IOException e) {
throw new RuntimeException(e);
}
};
Lambda表达式引用的局部变量必须是最终的( final)
可以把方法引用看作针对仅仅涉及单一方法的Lambda的语法糖
如何构建方法引用
方法引用主要有三类。
(1) 指向静态方法的方法引用(例如Integer的parseInt方法, 写作Integer::parseInt)。
(2) 指向任意类型实例方法的方法引用 ( 例 如 String 的 length 方 法 , 写 作
String::length)。
(3) 指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction
用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensiveTransaction::getValue)。
总结:
Lambda表达式可以理解为一种匿名函数:它没有名称,但有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常的列表。
Lambda表达式让你可以简洁地传递代码。
函数式接口就是仅仅声明了一个抽象方法的接口。
只有在接受函数式接口的地方才可以使用Lambda表达式。
Lambda表达式允许你直接内联,为函数式接口的抽象方法提供实现,并且将整个表达式作为函数式接口的一个实例。
Java 8自带一些常用的函数式接口,放在java.util.function包里,包括Predicate<T>、 Function<T,R>、 Supplier<T>、 Consumer<T>和BinaryOperator<T>等。
为了避免装箱操作,对Predicate<T>和Function<T, R>等通用函数式接口的原始类型特化: IntPredicate、 IntToLongFunction等。
环绕执行模式(即在方法所必需的代码中间,你需要执行点儿什么操作,比如资源分配和清理)可以配合Lambda提高灵活性和可重用性。
Lambda表达式所需要代表的类型称为目标类型。
方法引用让你重复使用现有的方法实现并直接传递它们。
Comparator、 Predicate和Function等函数式接口都有几个可以用来结合Lambda表达式的默认方法。
代码
package com.hw;
import java.util.*;
import java.util.function.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
public class Main {
public static void main(String[] args) {
List<Apple> lists = Arrays.asList(new Apple[]{
new Apple(10), new Apple(20), new Apple(30)
});
/*Collections.sort(lists, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
});*/
// 方法引用
lists.sort(Comparator.comparing(Apple::getWeight));
lists.sort(Comparator.comparing(Apple::getWeight).reversed()); // 逆序排列
lists.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
List<String> str = Arrays.asList("a","b","A","B");
str.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
str.sort(String::compareToIgnoreCase);
Function<String, Integer> function1 = (String s) -> s.length();
Function<String, Integer> function2 = String::length;
BiPredicate<List<String>, String> c1 = List::contains;
// 构造函数引用
Supplier<Apple> s1 = () -> new Apple();
Apple aa1 = s1.get();
Supplier<Apple> s2 = Apple::new;
Apple aa = s2.get();
Function<Integer, Apple> fu11 = (a) -> new Apple(a);
Apple ab11 = fu11.apply(11);
Function<Integer, Apple> fu1 = Apple::new;
Apple ab1 = fu1.apply(11);
BiFunction<Integer, String, Apple> fu111 = (a, b) -> new Apple(a, b);
Apple ab111 = fu111.apply(11, "test");
BiFunction<Integer, String, Apple> fua1 = Apple::new;
Apple aba1 = fua1.apply(11, "test");
// 比较器链
lists.sort(Comparator.comparing(Apple::getName).reversed().thenComparing(Apple::getWeight));
// 谓词复合
// 谓词接口包括三个方法: negate、 and和or
Predicate<Apple> predicate11 = (a) -> a.getWeight() > 10;
Predicate<Apple> predicate111 = predicate11.negate(); // 非
Predicate<Apple> predicate12 =
predicate11.and((a) -> a.getName().equals(""))
.or((a) -> a.getWeight() < 100);
lists.stream().forEach(l -> System.out.println(l.getWeight()));
List<Apple> lists1 = Arrays.asList(new Apple[]{
new Apple(10, "aa"), new Apple(20, "bb"), new Apple(30, "cc"),
new Apple(10, "dd"), new Apple(20, "b1")
});
// 函数复合
// 流水线式操作
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g); // g(f(x))
Function<Integer, Integer> h1 = f.compose(g); // f(g(x))
Map<Integer, List<Apple>> map =
lists1.stream().filter(l -> l.getWeight() > 1)
.collect(groupingBy(Apple::getWeight));
for(Map.Entry<Integer, List<Apple>> entrySet : map.entrySet()) {
System.out.println(entrySet.getValue().toString());
}
List<Apple> l1 = lists1.stream().collect(toList());
List<String> l2 = lists1.stream().map(Apple::getName).collect(toList());
Comparator<Apple> comparator = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
Comparator<Apple> comparator1 = new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
};
Function<String, Integer> func1 = (String s) -> s.length();
Function<Apple, Boolean> func2 = (Apple a) -> a.getWeight() > 100;
/*Consumer<Integer> co = (int x, int y) -> {
System.out.println(x + y);
System.out.println(x - y);
};*/
Supplier<Integer> supplier = () -> 10;
// 同一个Lambda可用于多个不同的函数式接口
Comparator<Apple> comparator2 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
BiFunction<Apple, Apple, Integer> biFunction = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
ToIntBiFunction<Apple, Apple> biFunction1 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
Runnable runnable = () -> System.out.println("11");
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("11");
}
};
}
}
网友评论