转自:https://www.twle.cn/c/yufei/java8/java8-basic-lambda-callable-argument.html
本章节我们重点来讲讲 Java 8 中的 Runnable
Lambda 表达式。众所周知,Java 8 中的 Runable
和 Callable
两个接口都添加了 @FunctionalInterface
注解,因此我们可以直接使用 Lambda 表达式来代替它们的 run()
和 call()
方法
Runnable 表达式
Java 8 开始支持 Lambda 表达式,所以,好像,一夜间,所有添加了 @FunctionalInterface
注解的方法都可以使用 Lambda 表达式来创建实例,Runnable
也不例外,我们可以直接使用一个 Lambda 表达式来创建它的实例
Runnable r = () -> System.out.println("Hello World!"); Thread th = new Thread(r); th.start();
运行结果输出为 Hello World
,是不是很神奇,如果没有 Lambda 表达式,那么原来的代码可能如下
Runnable r = new Runnable() { @Override public void run() { System.out.println("Hello World!"); } }; Thread th = new Thread(r); th.start();
如果我们的 Lambda 表达式需要多行代码,可以用一对打括号 {}
扩起来,就像下面这样
Runnable r = () -> { Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName()); list.forEach(style); };
如果 Lambda 表达式需要使用到外部的参数,那么必须对参数添加 final
修饰符表示参数不可变更。
final List<Book> list = Arrays.asList(new Book(1, "Ramayan"), new Book(2, "Mahabharat")); Runnable r = () -> { Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName()); list.forEach(style); };
==========@FunctionalInterface=======
@FunctionalInterface
注解的接口叫作函数式接口,可以用Lambda表达式来创建接口对象,能极大地提高编码效率。
public class FunctionalInterfaceExample {
public static void main(String[] args) {
Integer[] array = {1, 4, 3, 2};
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}); // 倒序排序
System.out.println(JSON.toJSONString(array));
Arrays.sort(array, (v1, v2) -> v1 - v2); // 正序排序
System.out.println(JSON.toJSONString(array));
}
}
// output
//[4,3,2,1]
//[1,2,3,4]
传统排序与使用函数式接口排序,代码从6行缩减到1行。
不过Lambda表达式可能会导致性能稍差
public class FunctionalInterfaceExample {
public static void main(String[] args) {
Integer[] array = {1, 4, 3, 2};
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < 1000; i++) {
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}); // 倒序排序
}
stopWatch.stop();
System.out.println(stopWatch.getTime());
stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < 1000; i++) {
Arrays.sort(array, (v1, v2) -> v1 - v2); // 正序排序
}
stopWatch.stop();
System.out.println(stopWatch.getTime());
}
}
// output(这里耗时相关几十倍,将循环数调大,性能差异慢慢变小)
// 2
// 126
设计自己的FunctionalInterface
- 给接口添加
@FunctionalInterface
注解 - 函数式接口,只能有一个未实现的方法声明
- 可以有0到多个
default
和static
方法声明
FunctionalInterface本质上还是Interface,声明与使用跟正常接口一样,只是附加了lambda表达式功能。
假如我想设计一个处理器,用来在某方法执行前后打印信息。
public class FunctionalInterfaceExample {
public static <T> void handle(Handler<T> handler, T t) {
System.out.println("before");
handler.handle(t);
System.out.println("after");
}
public static void main(String[] args) {
String hello = "Hello world!";
handle(t -> System.out.println(t), hello);
// handle(System.out::println, hello); // 我们也可以用方法引用
}
}
@FunctionalInterface
interface Handler<T> {
void handle(T t);
}
// output
// before
// Hello world!
// after
jdk自带常用接口分类
由于当初在学习这些接口的方法时,老是记不住,故自己整理了一下记忆口诀,如果你有更好的,还望不吝分享。
口诀 | 接口签名 | 接口方法 |
---|---|---|
应用(apply)函数(Function),有进有出 | Function<T, R> | R apply(T t) |
接受(accept)消费(Consumer),只进不出 | Consumer<T> | void accept(T t) |
测试(test)谓词(Predicate),返回真假 | Predicate<T> | boolean test(T t) |
获得(get)供给(Supplier),不劳而获 | Supplier<T> | T get() |
Function
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Supplier
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Comparator
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Comparator的常用静态方法
方法名 | 作用 |
---|---|
Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) | 返回根据对象的key值按指定规则排序的排序器 |
Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) | 生成根据对象的key值并按key值默认规则排序的排序器 |
Comparator<T> thenComparing(Comparator<? super T> other) | 当前排序相等的情况下,再按指定的Comparator排序 |
Comparator<T> reversed() | 按当前排序规则倒序 |
Comparator<T> nullsFirst(Comparator<? super T> comparator) | 让comparator能处理null值,并将null值放在最前面 |
Comparator<T> nullsLast(Comparator<? super T> comparator) | 让comparator能处理null值,并将null值放在最后面 |
public class ComparatorTest {
private int a;
private int b;
public ComparatorTest(int a, int b) {
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public ComparatorTest setA(int a) {
this.a = a;
return this;
}
public int getB() {
return b;
}
public ComparatorTest setB(int b) {
this.b = b;
return this;
}
@Override
public String toString() {
return "\n" + a + " : " + b;
}
public static void main(String[] args) {
List<ComparatorTest> list = new ArrayList() {{
add(new ComparatorTest(1, 1));
add(new ComparatorTest(1, 2));
add(new ComparatorTest(2, 3));
add(null);
add(new ComparatorTest(2, 1));
add(new ComparatorTest(3, 4));
add(new ComparatorTest(3, 1));
}};
// 按b属性倒序,再按a属性倒序排列,null放最前面
// 相当于SQL: sort by b desc, a desc
list.sort(Comparator.nullsFirst(Comparator
.comparing(ComparatorTest::getB)
.reversed()
.thenComparing(Comparator
.comparing(ComparatorTest::getA)
.reversed())));
System.out.println(list);
}
}
// output:
// [null,
// 3 : 4,
// 2 : 3,
// 1 : 2,
// 3 : 1,
// 2 : 1,
// 1 : 1]
Runnable 与 Callable
方法声明 | 记忆方法 |
---|---|
void run() | 跑步(run),应该轻装上阵,简称空跑 |
V call() | 打电话(call),期待返回对方的声音 |
Runnable
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Callable
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
4人点赞
作者:readyou
链接:https://www.jianshu.com/p/2f35ba719fea
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。