目录
为什么引入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表达式的语法格式:
(参数列表 ) - > { 语句或语句块 }
【例子展示】
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);
在《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

- 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

- 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);
1、所需类型不同;
匿名内部类:接口,抽象类,也可具体类;
Lambda表达式: 接口;
2、使用限制
接口只有一个抽象方法,两者都可以使用;多个抽象方法,只能使用匿名内部类;
3、实现原理
匿名内部类,编译之后,产生单独的.class字节码文件;
lambda表达式:编译之后,没有单独的.class字节码文件,对应的字节码在运行时动态生成,不会保留到本地的硬盘之中;
别逼我求你……
