Java8特性: Lamda

Posted 唐微港

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8特性: Lamda相关的知识,希望对你有一定的参考价值。

函数式接口

函数式接口定义

  1. 只包含一个抽象方法;

  2. 可以包含非抽象方法;

  3. 最好用注解“@FunctionalInterface”保证抽象方法的唯一性。

    例如:以下接口

public interface FunctionInterfaceTest<T, R> {

    //唯一的抽象方法
    R getSum(T a);

    //Java8中允许接口中有静态的实现方法
    static <T> DemoTest<T, T> getInstance() {
        return t -> t;
    }

    static DemoTest<Integer, Integer> getInstance2() {
        return t -> {
            t *= 6;
            return t + 1;
        };
    }
}

注意:

  1. Java8中允许接口中有静态的实现方法
  2. 接口中允许有一个default的默认实现方法

Java8 内置函数式接口

Consumer : 消费型接口,void accept(T t)

Supplier : 供给型接口,T get();

Function<T, R> : 函数型接口,R apply(T t);

Predicate : 断言型接口,boolean test(T t);

Lamada表达时

lamada表达时使用需要借助于函数式接口

Lamada表达式说明

  1. 左侧:指定了Lambda表达式需要的所有参数

  2. 右侧:指定了Lambda体,即lambda表达式要执行的功能,类似于方法体

  3. 类型,参数类型可以省略不写,jvm会自动推导

    注意事项

  4. 左侧只有一个参数时可以不写小括号()

  5. 右侧只有一条语句时可以不写大括号{ }

  6. 参数类型和返回类型也可以省略,jvm会帮助自动推导

    Lamada语法形式(实现自定义函数式接口)

  7. 定义多个函数式接口,后面的Lambda说明也使用这些函数式接口

/**无参无返回值*/
@FunctionalInterface
public interface DefineInterface {
    void method();
}


/**一个有参数无返回*/
@FunctionalInterface
public interface DefineInterface {
    void method(int a);
}


/**多参数无返回*/
@FunctionalInterface
public interface DefineInterface {
    void method(int a, int b);
}


/*** 无参有返回*/
@FunctionalInterface
public interface DefineInterface {
    int method();
}


/**一个参数有返回值*/
@FunctionalInterface
public interface DefineInterface {
    int method(int a);
}


/**多个参数有返回值*/
@FunctionalInterface
public interface DefineInterface {
    int method(int a, int b);
}
  1. 左边只有一个参数时可以省略()不写
  2. 右边只有一条语句时可以省略{ }不写
public static void main(String[] args) {

        //无参无返回
        DefineInterface df = () -> {
            System.out.println("df");
        };
        df.method();

        //一个参数无返回
        DefineInterface df = (a) -> {
            System.out.println("df param:" + a);
        };
        df.method(6);

        //多个参数无返回
        DefineInterface df = (a,b) -> {
            System.out.println("df param:" + "{" + a +"," + + b +"}");
        };
        df.method(6, 8);

        //无参有返回值
        DefineInterface df = () -> {
            System.out.print("df");
            return 1;
        };
        int res = df.method();
        System.out.println("return:" + res);
    
    
        //一个参数有返回值
        DefineInterface df = (int a) -> {
            System.out.println("df param:" + a);
            return 1;
        };
        int res2 = df.method(6);
        System.out.println("return:" + res2);

        //多个参数有返回值
        DefineInterface df = (int a, int b) -> {
            System.out.println("df param:" + "{" + a + "," + b +"}");
            return 1;
        };
        int res3 = df.method(6, 8);
        System.out.println("return:" + res3);
    }

Lamada表达式引用方法(指向已实现的方法)

有时候我们不一定要自己重写某个匿名内部类的方法,我们可以利用 lambda表达式的接口快速指向一个已经被实现的方法

语法

方法归属者::方法名

静态方法的归属者为类名

普通方法归属者为对象

public class Exe1 {
    
    /**
     * 要求
     * 1.参数数量和类型要与接口中定义的一致
     * 2.返回值类型要与接口中定义的一致
     */
    public static int doubleNum(int a) {
        return a * 2;
    }

    public int addTwo(int a) {
        return a + 2;
    }
    
    public static void main(String[] args) {
        //方式一:Lamad直接指向方法
        ReturnOneParam lambda1 = a -> doubleNum(a);
        System.out.println(lambda1.method(3));

        //方式二:::静态传递   lambda2 引用了已经实现的 doubleNum 方法(静态用方法名)
        ReturnOneParam lambda2 = Exe1::doubleNum;
        System.out.println(lambda2.method(3));

        Exe1 exe = new Exe1();

        //方式二:::静态传递   lambda4 引用了已经实现的 addTwo 方法(非静态用对象名)
        ReturnOneParam lambda4 = exe::addTwo;
        System.out.println(lambda4.method(2));
    }
}

Lambda表达式创建线程

public class LamadaSTD {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                System.out.println( "线程" + i);
            }
        });
        t.start();
    }

}

Lambda表达式遍历集合

    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();

        Collections.addAll(list, 1,2,3,4,5);

        //lambda表达式 方法引用传递
        list.forEach(System.out::println);
        //lambda表达式 方法引用
        list.forEach(element -> {
            System.out.print(element);
        });
    }

Lambda闭包问题

把注释放开会报错,告诉我 num 值是 final 不能被改变。这里我们虽然没有标识 num 类型为 final,但是在编译期间虚拟机会帮我们加上 final 修饰关键字。

public static void main(String[] args) {

        int num = 10;

        Consumer<String> consumer = ele -> {
            System.out.println(num);
        };
        //这里的注释不能打开上面Lambda表达式中的num会提示错误
        //num = num + 2;
        consumer.accept("hello");
    }

可参考:

https://www.cnblogs.com/haixiang/p/11029639.html

以上是关于Java8特性: Lamda的主要内容,如果未能解决你的问题,请参考以下文章

Java8特性: Lamda

java8的lamda有啥意义

JAVA8新特性——方法引用

Java lamda和predicate用法例子

Java lamda和predicate用法例子

lamda和匿名内部类