@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;
}