Java 杂谈Android基础知识程序员技术栈

【Java】3.0 Java中lambda表达式(上)

2019-07-11  本文已影响5人  bobokaka
1.0 lambda表达式是JDK8新增的功能,它显著增强了Java。

自C#和C++等语言都添加了lambda表达式后,Java8也开始不甘人后,继续保持自身的活力和创造性。lambda表达式正在重塑Java,将影响到几乎所有的Java程序员。

2.0 lambda表达式本质是一个匿名(即未命名)方法。实现和理解其实很简单。
() -> 123.45

上面的内容,效果等同于如下所示:

double myMeth(){
        return 123.45;
}

第二个代码中小括号内的内容就是第一个代码小括号中的内容,有参数或者无参数。

(n) -> (n%2) == 0

上面的内容,效果等同于如下所示:

boolean myExample(int n){
       return (n%2) == 0;
}
3.0 高级的来了: 单个表达式
3.1 无参数的单个lambda表达式。先看完整代码。
package com.edpeng.game1;

interface MyNumber {
    // 从JDK8开始,可以为接口声明默认行为,即所谓的“默认方法”
    double getValue();
}

public class test1 {

    public static void main(String[] args) {
        MyNumber myNum;
        // 第一个例子
        myNum = () -> 123.45;
        System.out.println("第一个例子输出结果为:" + myNum.getValue());

        // 第二个例子,Math.random(),生成0-1之间的伪随机数
        myNum = () -> Math.random() * 100;
        System.out.println("第二个例子第一个值输出结果为:" + myNum.getValue());
        System.out.println("第二个例子第二个值输出结果为:" + myNum.getValue());

//      myNum = () -> "123.45";//会报错!无法编译运行。
    }
}

执行结果如下:


图片.png
3.2 有参数的单个lambda表达式。下面是有参表达式的完整代码实例:
package com.edpeng.game1;

interface NumericTest {
    // 从JDK8开始,可以为接口声明默认行为,即所谓的“默认方法”
    boolean test(int n);
}

public class test1 {

    public static void main(String[] args) {
        // 例子1
        NumericTest isEven = (n) -> (n % 2) == 0;
        int number = 10;
        if (isEven.test(number)) {
            System.out.println(number + " 能被2整除。");
        } else {
            System.out.println(number + " 不能被2整除。");
        }

        // 例子2
        NumericTest isNonNeg = (n) -> n >= 0;
        number = 1;
        if (isNonNeg.test(number)) {
            System.out.println(number + " 是自然数。");
        } else {
            System.out.println(number + "不是自然数。");
        }
        number = -1;
        if (isNonNeg.test(number)) {
            System.out.println(number + "是自然数。");
        } else {
            System.out.println(number + "不是自然数。");
        }
    }
}

运行结果如下:


图片.png
4.0 块lambda表达式

具体格式如下:

() -> { };
4.1 看代码就懂了,无非就是箭头符号后面不止一句语句,可以用花括号整合在一起执行。
package com.edpeng.game1;

interface Numericfunc {
    int func(int n);
}

public class test1 {

    public static void main(String[] args) {
        Numericfunc numericfunc = (n) -> {
            int result = 1;
            for (int i = 1; i <= n; i++) {
                result = i * result;
            }
            return result;
        };
        // 3的阶乘:1*2*3
        System.out.println("3的阶乘是:" + numericfunc.func(3));
        // 5的阶乘:1*2*3*4*5
        System.out.println("5的阶乘是:" + numericfunc.func(5));
    }
}

执行结果为:


图片.png
4.2 在上面4.1中都是int型,下面可以举一个别的类型的实现。
package com.edpeng.game1;

interface Stringfunc {
    String func(String n);
}

public class test1 {

    public static void main(String[] args) {
        Stringfunc stringfunc = (str) -> {
            String result = "";
            int i;
            for (i = str.length() - 1; i >= 0; i--) {
                result += str.charAt(i);
            }
            return result;
        };

        System.out.println("将lambda字母颠倒输出为:\n" + stringfunc.func("lambda"));
        System.out.println("将Expression字母颠倒输出为: \n" + stringfunc.func("Expression"));
    }
}

执行结果为:


图片.png
5.0 泛型函数式接口。
5.1 上面4.2中已经阐述过了,这里需要再强调一下,lambda表达式自身不能指定类型参数。也因此,lambda表达式不能是泛型(当然,它本身存在类型推断,自带一些类似泛型的特征)。
5.2 但是,,lambda表达式关联的函数式接口可以是泛型。这时候,lambda表达式的目标类型由声明函数式接口引用时指定的参数类型决定。
5.3 基于此,我们可以把4.1和4.2中两个范例通过泛型函数式接口整合在一起。代码如下:
package com.edpeng.game1;

//这就叫做“泛型函数式接口”
interface SomeFunc<T> {
    T func(T t);
}

public class test1 {

    public static void main(String[] args) {

        // 4.1中的案例
        SomeFunc<String> reverse = (str) -> {
            String result = "";
            int i;
            for (i = str.length() - 1; i >= 0; i--) {
                result += str.charAt(i);
            }
            return result;
        };

        System.out.println("将lambda字母颠倒输出为:\n" 
        + reverse.func("lambda"));
        System.out.println("将Expression字母颠倒输出为: \n" 
        + reverse.func("Expression"));

        // 4.1中的案例等同于:
//      SomeFunc<String> re = new SomeFunc<String>() {
//
//          @Override
//          public String func(String t) {
//              // TODO Auto-generated method stub
//              String result = "";
//              int i;
//              for (i = t.length() - 1; i >= 0; i--) {
//                  result += t.charAt(i);
//              }
//              return result;
//          }
//      };
//      System.out.println("将lambda字母颠倒输出为:\n" +re.func("lambda"));

        // 4.2中的案例
        SomeFunc<Integer> factorial = (num) -> {
            int result = 1;
            for (int i = 1; i <= num; i++) {

                result = i * result;
            }
            return result;
        };
        // 3的阶乘:1*2*3
        System.out.println("3的阶乘是:" + factorial.func(3));
        // 5的阶乘:1*2*3*4*5
        System.out.println("5的阶乘是:" + factorial.func(5));
    }
}

执行结果为:


图片.png
6.0 作为参数传递lambda表达式

这个方面是lambda表达式的一种常见用途,极大的增强了Java的表达能力。
通过一个简单的例子演示就足够了,特别简单直观好理解,而且实用。

package com.edpeng.game1;

interface StringFunc {
    String func(String n);
}

class test1 {
    static String stringOp(StringFunc sf, String string) {
        return sf.func(string);
    }

    public static void main(String[] args) {
        //案例一:小学转大写
        String inStr = "lambda 表达式 加入 Java";
        String outStr;

        System.out.println("输入的字符串为: \n" + inStr);
        outStr = stringOp((str) -> str.toUpperCase(), inStr);
        System.out.println("该字符串的大写为: \n" + outStr);

        //案例二:去除文本空格
        outStr = stringOp((str) -> {
            String result = "";
            int i;

            for (i = 0; i < str.length(); i++) {
                if (str.charAt(i) != ' ') {
                    result += str.charAt(i);
                }
            }
            return result;
        }, inStr);

        System.out.println("删除空格的字符串为: \n" + outStr);

        //案例三:字符倒转
        StringFunc reverse = (str) -> {
            String result = "";
            int i;
            for (i = str.length() - 1; i >= 0; i--) {
                result += str.charAt(i);
            }
            return result;
        };
        System.out.println("重新转换的字符串为: \n" + stringOp(reverse, inStr));
    }
}

执行结果如下:


图片.png

这个并没有增加新的内容,只是将其中增加的这个特性再一次强调一下。案例一和案例二都可以简单表述为:

 outStr = stringOp(lambda表达式,inStr);

当然我们也看当这样使用时有些笨拙的,当块lambda表达式看上去特别长的时候,嵌入到方法调用中,很容易把块lambda赋给一个函数式接口变量。所以当使用案例三这种做法时,就显得很简单而且不易出错。案例三可以简单描述为:

 StringFunc reverse =lambda表达式;
 stringOp(reverse, inStr);
上一篇下一篇

猜你喜欢

热点阅读