美文网首页
跟我学java8之FunctionalInterface

跟我学java8之FunctionalInterface

作者: readyou | 来源:发表于2017-07-18 18:05 被阅读267次

    @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

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

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

    相关文章

      网友评论

          本文标题:跟我学java8之FunctionalInterface

          本文链接:https://www.haomeiwen.com/subject/jrgckxtx.html