跟我学java8之FunctionalInterface

@FunctionalInterface注解的接口叫作函数式接口,可以用Lambda表达式来创建接口对象,能极大地提高编码效率。

public class FunctionalInterfaceExample {
    public static void main(String[] args) {
        Integer[] array = {1, 4, 3, 2};
        Arrays.sort(array, new Comparator() {
            @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() {
                @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

  1. 给接口添加@FunctionalInterface注解
  2. 函数式接口,只能有一个未实现的方法声明
  3. 可以有0到多个defaultstatic方法声明

FunctionalInterface本质上还是Interface,声明与使用跟正常接口一样,只是附加了lambda表达式功能。

假如我想设计一个处理器,用来在某方法执行前后打印信息。

public class FunctionalInterfaceExample {
    public static  void handle(Handler 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 {
    void handle(T t);
}
// output
// before
// Hello world!
// after

jdk自带常用接口分类

由于当初在学习这些接口的方法时,老是记不住,故自己整理了一下记忆口诀,如果你有更好的,还望不吝分享。

口诀 接口签名 接口方法
应用(apply)函数(Function),有进有出 Function R apply(T t)
接受(accept)消费(Consumer),只进不出 Consumer void accept(T t)
测试(test)谓词(Predicate),返回真假 Predicate boolean test(T t)
获得(get)供给(Supplier),不劳而获 Supplier T get()

Function

@FunctionalInterface
public interface Function {
    R apply(T t);
}

Consumer

@FunctionalInterface
public interface Consumer {
    void accept(T t);
}

Predicate

@FunctionalInterface
public interface Predicate {
    boolean test(T t);
}

Supplier

@FunctionalInterface
public interface Supplier {
    T get();
}

Comparator

@FunctionalInterface
public interface Comparator {
    int compare(T o1, T o2);
}

Comparator的常用静态方法

方法名 作用
Comparator comparing(Function keyExtractor, Comparator keyComparator) 返回根据对象的key值按指定规则排序的排序器
Comparator comparing(Function keyExtractor) 生成根据对象的key值并按key值默认规则排序的排序器
Comparator thenComparing(Comparator other) 当前排序相等的情况下,再按指定的Comparator排序
Comparator reversed() 按当前排序规则倒序
Comparator nullsFirst(Comparator comparator) 让comparator能处理null值,并将null值放在最前面
Comparator nullsLast(Comparator 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 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 call() throws Exception;
}

你可能感兴趣的:(跟我学java8之FunctionalInterface)