IT@程序员猿媛程序员Java 杂谈

java 函数式编程(1)

2019-04-15  本文已影响78人  zidea
lambda-expression.png

命令式编程关注对过程,也就是怎么做是回答 3W 的问题( When、Why 和 How)
但是在函数式编程的世界里关注是做什么,也就是回答 what 的问题

函数式编程的好处

一个最简单需求就是我们从数组中找到最小数,这样逻辑出现在每一个应用中,我们在熟悉不过了,拿来就写。但是我们平时每天都做的是并不一定是最佳方法。先用命令式编程方式实现一下。

public static void main(String[] args) {
         int[] courses = {1,2,3,5,6,7};
         int min = Integer.MAX_VALUE;
        for (int i:courses
             ) {
            if(i < min){
                min= i;
            }
        }

    }

看起来有点复杂,有人会惊讶这还复杂呀,多简单。您说简单是因为这种方式是你熟悉的,所以认为这种方法简单,其实熟悉并非简单。这里首先产生中间变量 min 这对结果是没有用处的。

System.out.println(min);

        int min2 = IntStream.of(courses)
                .min().getAsInt();
        System.out.println(min2);

如果这里数据有上亿条,通过 for 循环是扛不住这么大数据,我们就需要多线程并行来处理数据,我们首先对数据划分区域,然后每一个区域由一个线程来计算其最小值,最后进行合并找出其最小值,但是对于 java8 的流处理我们只需要将 parallel()就可以实现上面效果,我们不需要自己实现,新的 api 已经为我们实现这些。

int min2 = IntStream.of(courses).parallel()
                .min().getAsInt();
        System.out.println(min2);

创建线程是 java 并发编程中不可缺少也是最基本的 coding。我们创建了 Thread 然后接受一个匿名函数做出参数,其中有一个 run 方法是我们在新开的线程中进行的计算。

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("ok");
            }
        }).start();
        
    }

lambda 表达式在 java 中写法。

 new Thread(()-> System.out.println("ok")).start();

我们看一看 Runnable 这是一个接口,接口中有 run 方法,这个方法没有输入也没有输出,不过 runanble 是一个接口的示例,lambda 表达式其实就是就是返回指向对象接口的对象实例。

Runnable target = () -> System.out.println("ok");
        new Thread(target).start();

将刚刚代码重构一下就看 lambda 更加清晰了。

interface Func {
    int doubleNum(int i);
}

我们可以写成

Func fun1 = (i) -> i * 2;
        Func fun2 =  i -> i * 2;

        Func fun3 = (int i) -> {
            return  i * 2;
        };

我们知道 lambda 是返回一个实现接口的实例,但是对什么样接口可以作为 lambda 返回值类型是有限制的。我们的接口只能有一个方法。这个应该很好理解,函数接口

通过注解@FunctionalInterface来修饰接口,表示这个接口为函数式接口,在编译期进行来检查该接口是否符合函数式接口。

@FunctionalInterface
interface Func {
    int doubleNum(int i);
}
th-3.jpeg

单一原则是程序设计的原则,所以我们尽量将接口进行细化拆分。在 java 的 JDK8 中引进了 default 可以添加一些接口自身已经默认实现的方法。

@FunctionalInterface
interface Func {
    int doubleNum(int i);
    default int add(int x, int y){
        return x + y;
    }
}
System.out.println(fun1.add(2,3));

我们将接口进行拆分后,可以通过接口继承实现多个接口组合。

@FunctionalInterface
interface Func {
    int doubleNum(int i);
    default int add(int x, int y){
        return x + y;
    }
}

@FunctionalInterface
interface FuncA {

    int doubleNum(int i);

    default int add(int x, int y){
        return x + y;
    }
}

@FunctionalInterface
interface FuncB extends Func,FuncA{

    @Override
    default int add(int x, int y) {
        return Func.super.add(x,y);
    }
}

在多个接口组合情况下,如果继承的多个接口都有一个同名的默认方法,我们的接口就需要显式地指定使用哪个接口方法或对该方法进行复写。

上一篇下一篇

猜你喜欢

热点阅读