Java8 巨强大的新特性 lambda表达式

目录

一、定义

二、lambda表达式的语法

 三、常见的lambda表达式使用场景

四、再提经典使用 

五、匿名内部类与lambda表达式区别


为什么引入lambda表达式?

到目前为止(java7之前),在Java中传递一个代码段并不方便,你不能直接传递代码段。因为Java是一种面向对象的语言,所以必须创建一个对象,由这个对象实现所需方法片段》。

设计者们做了多年尝试,终于找到了一种适合Java的设计——lambda表达式。

一、定义

《Java核心技术 I》里是这么定义的:

lambda表达式是一个可传递的代码块,可以在以后一次或多次执行,它采用了一种简洁的方式来定义代码块。

1、传统方式调用

//接口实现
public class Runnable1 implements Runnable {
    @Override
    public void run() {
        System.out.println("执行了多线程方法!");
    }
}

public class MyLambda1 {
    public static void main(String[] args) {
        Runnable1 lambda1=new Runnable1();
        Thread thread=new Thread(lambda1);
        thread.run();
    }
}

2、匿名内部类

public class MyLambda1 {
    public static void main(String[] args) {
        Runnable lambda2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("执行了多线程方法!");
            }
        };
        Thread thread=new Thread(lambda2);
        thread.run();
    }
}

3、lambda表达式

public class MyLambda1 {
    public static void main(String[] args) {
        //3、lambda表达式
        Thread thread=new Thread(()->{
            System.out.println("执行了多线程方法!");
        });
        thread.run();
    }
}

可能会有同学要问了,匿名内部类跟lambda表达式感觉没多大区别啊!能不能不学啊!

lambda表达式确实写法简洁了,而且实现方式是不同(后面会比较二者的不同)。

二、lambda表达式的语法

Lambda表达式的语法格式:

(参数列表  ) - > { 语句或语句块 }

  • ( ):若为空,则接口方法没有参数
  • - >:箭头指向{}中的方法代码块
  • { }:包含一段代码块,即方法体中的内容

【例子展示】

1、无参数无返回值

public interface Cat {
    void say();
}

public class Lambda2 {
    public static void main(String[] args) {
        testCat(() -> {
            System.out.println("猫叫声:喵!喵!喵!");
        });
    }

    public static void testCat(Cat cat) {
        cat.say();
    }

}

2、带参数无返回值

public interface Dog {
    void call(String msg);
}


public class Lambda2 {
    public static void main(String[] args) {
        testDog((String msg) -> {
            System.out.println("狗叫声:" + msg);
        });

    }

    public static void testDog(Dog dog) {
        dog.call("汪!汪!汪!");
    }

}

3、带参数有返回值

public interface Operation {
    int add(int n, int m);
}

public class Lambda2 {
    public static void main(String[] args) {
        testOperation((int n,int m) -> {
            return n+m;
        });
    }


    public static void testOperation(Operation operation) {
        System.out.println(operation.add(10, 20));
    }
}

【 写法简化】:

  • 单个参数可省略()
  • 参数类型可以省略(必须同时省略或者不省略)
  • 方法体单语句可以省略 {  }
        /省略参数括号、方法体括号
        testDog(msg -> System.out.println("狗叫声:" + msg));

        //方法引用
        //打印对象是传入参数
        testDog(System.out::println);

 三、常见的lambda表达式使用场景

在《JAVA核心技术 I》中这样描述:

        使用 lambda表达式的重点是延迟执行(deferred execution)毕竟,如果想要立即执行代
码,完全可以直接执行,而无须把它包装在一个 lambda表达式中。之所以希望以后再执行
代码,这有很多原因,如:

  • 在一个单独的线程中运行代码;
  • 多次运行代码;
  • 在算法的适当位置运行代码(例如,排序中的比较操作);
  • 发生某种情况时执行代码(如,点击了一个按钮,数据到达,等等);
  • 只在必要时才运行代码;

1、重复执行代码:

    repeat(10, () -> System.out.println("Hello,World!"));


    public static void repeat(int n, Runnable action) {
        for (int i = 0; i < n; i++) {
            action.run();
        }
    }

 2、延迟执行(必要时才运行、发生某种情况时执行代码)

javaFX中给按钮绑定事件,某一事件才触发按钮

Button button = new Button("按钮");

button.setOnAction(event -> {
    
    //do something

});

3、在算法的适当位置运行代码(例如,排序中的比较操作)

在compartor的比较方法执行结束前,不会进行排序。

        //自定义数组
        String [] arg={"acc","ddd","aaa","bbb","ccc"};

        Arrays.sort(arg,(first,second)->{
            return first.length()-second.length();
        });

四、再提经典使用 

1、Java的四大函数式接口

 a、Consumer

表示接受单个输入参数且不返回结果的操作。 与大多数其他功能界面不同,Consumer被期望通过副作用来操作。 

public class ConsumerTest1 {
    public static void main(String[] args) {
        String [] arr={"花木兰,21","小乔,23","孙尚香,22"};

        consumer(arr, (s)->{
            System.out.print(s.split(",")[0]);
        }, new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(","+Integer.parseInt(s.split(",")[1]));
            }
        });
    }

    //消费方法
    public static void consumer(String[] arr, Consumer<String> con1, Consumer<String> con2) {
        for (String str : arr) {
            con1.andThen(con2).accept(str);
        }
    }
}

b、Supplier

  • 表示结果的提供者。  
  • 并不要求每次调用供应商时都返回一个新的或不同的结果。  
  • 这是一个函数式接口,其函数方法是get()。 

public class SupplierTest {
    public static void main(String[] args) {
        String s1 = getString(() -> {
            return "彭于晏";
        });
        System.out.println("lambda表达式:"+s);
    }

    //消费方法
    public static String getString(Supplier<String> sup){
       return sup.get();
    }
}

c、Predicate

  • 表示一个参数的谓词(布尔值函数)。  
  • 这是一个功能接口,其功能方法是test(Object)。

public class PredicateTest {
    public static void main(String[] args) {
        String[] arg = {"aaaa", "bb", "cccc"};
        List<String> stringList = filter(arg
                , (obj) -> obj.toString().startsWith("a")
                , (obj) -> obj.toString().length() > 3);
        System.out.println(stringList.get(0));
    }

    public static List<String> filter(String[] arg, Predicate p1, Predicate p2) {
        List<String> result = new ArrayList<>();
        for (String s : arg) {
            if (p1.and(p2).test(s)) {
                result.add(s);
            }
        }
        return result;
    }
}

d、Function

2、steam流的使用

需求:字符数组中去掉以首字为d开头,再得到所有长度大于3的字符串,再按字典序排序输出。

        //自定义数组
        String [] arg={"acc","ddd","aaa","bbb","ccc"};
        Arrays.stream(arg)
                .filter((obj)->obj.toString().startsWith("a"))
                .filter((obj)->obj.toString().length()>3)
                .forEach(System.out::println);

五、匿名内部类与lambda表达式区别

1、所需类型不同;

匿名内部类:接口,抽象类,也可具体类;

Lambda表达式: 接口;

2、使用限制

接口只有一个抽象方法,两者都可以使用;多个抽象方法,只能使用匿名内部类;

3、实现原理

匿名内部类,编译之后,产生单独的.class字节码文件;

lambda表达式:编译之后,没有单独的.class字节码文件,对应的字节码在运行时动态生成,不会保留到本地的硬盘之中;


觉得文章好不错的话三连支持一下吧!

别逼我求你……

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值