Lambda表达式

1.Lambda简介

Lambda表达式是JDK8的一个新特性,可以取代大部分的匿名内部类,写出更优雅的java代码,尤其在集合的遍历和其他集合操作中可以极大地优化代码结构。
JDK也提供了大量的内置函数式接口供我们使用,使得Lambda表达式的运用更加方便,高效。

2.对接口的要求

虽然使用Lambda表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用Lambda表达式来实现。Lambda规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
JDK8中有另一个新特性:default,被default修饰的方法会有默认实现,不是必须被实现的方法,所以不影响Lambda表达式的使用。

3.@FunctionalInterface

修饰函数式接口的,要求接口中的抽象方法只有一个。这个注解往往会和lambda表达式一起出现。
作用:验证当前接口是否只有一个需要被实现的方法,如果不满足,就编译报错。
所有它就是为lambda表达式而生的。

@FunctionalInterface
public interface MyInterface {
    void a();
    default void b(){

    };
}

4.Lambda基础语法-准备工作

语法形式为() -> {},其中()用来描述参数列表,{}用来描述方法体,->为lambda运算符,读作(goes to)

package lambda;

public interface LambdaInterface {
}


/**
 * 无返回无参数
 */
@FunctionalInterface
interface NoReturnNoParam{
    void method();
}

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

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

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

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

/**
 * 有返回有多个参数
 */
@FunctionalInterface
interface ReturnMultiParam{
    int method(int a,int b);
}

5.Lambda基本语法-测试

package lambda;

/**
 * @author 葡萄
 * 基础语法测试
 */
public class LambdaTest01 {
    public static void main(String[] args) {
        //无参无返回
        NoReturnNoParam noReturnNoParam = () -> {
            System.out.println("ok");
            System.out.println("ok");
        };
        noReturnNoParam.method();
        //一个参数无返回
        NoReturnOneParam noReturnOneParam = (int a) -> {
            System.out.println(a);
            System.out.println(a);
        };
        noReturnOneParam.method(10);
        //多个参数无返回
        NoReturnMultiParam noReturnMultiParam = (int a,int b) -> {
            System.out.println(a);
            System.out.println(b);
        };
        noReturnMultiParam.method(10,20);
        //无参有返回
        ReturnNoParam returnNoParam = () -> {
            System.out.println("ok");
            return 110;
        };
        System.out.println(returnNoParam.method());
        //一个参数有返回
        ReturnOneParam returnOneParam = (int a) -> {
            return a+1000;
        };
        System.out.println(returnOneParam.method(10));
        //多个参数有返回
        ReturnMultiParam returnMultiParam = (int a,int b) -> {
            return a+b;
        };
        System.out.println(returnMultiParam.method(10,20));
    }
}

6.Lambda基本语法-简化

package lambda;

/**
 * @author 葡萄
 * 基础语法测试-简化
 */
public class LambdaTest02 {
    public static void main(String[] args) {
        int num = 1000;
        //1.简化参数类型,可以不写参数类型,但是必须所有参数都不写
        NoReturnMultiParam noReturnMultiParam = (a,b) -> {
            System.out.println(a+b);
        };

        //2.简化参数小括号,如果只有一个参数,则可以省略参数小括号
        NoReturnOneParam noReturnOneParam = a -> {
            System.out.println(a);
            System.out.println(a);
        };
        //3.简化方法体大括号,如果方法体只有一条语句,则可以省略方法体大括号
        NoReturnMultiParam noReturnMultiParam1 = (a,b) -> System.out.println(a+b);
        //4.如果方法体只有一条语句,并且是return语句,则可以省略方法体大括号
        ReturnMultiParam returnMultiParam = (a,b) -> a+b;
        ReturnMultiParam returnMultiParam1 = (a,b) -> num;
        ReturnMultiParam returnMultiParam3 = (a,b) -> num();
        ReturnMultiParam returnMultiParam2 = new ReturnMultiParam() {
            @Override
            public int method(int a, int b) {
                return num();
            }
        };
    }

    public static int num(){
        return 10000;
    }
}

7.Lambda表达式常用示例

7.1Lambda表达式引用方法

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

  • 语法:方法归属者::方法名 — 静态方法的归属者为类名,普通方法归属者为对象
  • 静态方法
    • 接口 对象名 = 类名::静态方法名;
  • 成员对象
    • 对象 对象名 = new 对象();
    • 接口 接口对象名 = 对象名::成员方法;
  • 要求:
    • 1.参数数量和类型要和接口中定义的一致
    • 2.返回值类型要与接口中定义的一致
package lambda;

/**
 * @author 葡萄
 * 基础语法测试-成员方法和静态方法的引用
 */
public class LambdaTest03 {
    public static void main(String[] args) {
        //使用有一个参数,并带有返回值
        ReturnOneParam returnOneParam = a -> {
            return a+100;
        };
        System.out.println(returnOneParam.method(100));
        //使用有一个参数,并带有返回值
        ReturnOneParam returnOneParam2 = a -> num();
        System.out.println(returnOneParam2.method(100));

        //使用有一个参数,并带有返回值 调用的某个类的静态方法
        ReturnOneParam returnOneParam3 = LambdaTest03::numOne;
        System.out.println(returnOneParam3.method(100));

        //使用有一个参数,并带有返回值 调用的某个类的成员方法
        LambdaTest03 lambdaTest03 = new LambdaTest03();
        ReturnOneParam returnOneParam4 = lambdaTest03::two;
        System.out.println(returnOneParam4.method(100));

        System.out.println("-------------");
        //不能调用静态方法
//        LambdaTest03 lambdaTest04 = new LambdaTest03();
//        LambdaTest03.num();
//        ReturnOneParam returnOneParam5 = lambdaTest04::numOne;
//        System.out.println(returnOneParam4.method(100));
    }

    /**
     * 这是LambdaTest03里面的一个静态方法
     * @return
     */
    public static int num(){
        return 10000;
    }

    /**
     * 这是LambdaTest03里面的一个静态方法
     * @return
     */
    public static int numOne(int a){
        return a+10000;
    }

    /**
     * 这是LambdaTest03里面的一个成员方法
     * @return
     */
    public int two(int a){
        return a+100000;
    }

}

7.2构造方法的引用

一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。

  • 语法 ItemCreatorBlankConstruct construct2 = Item::new;
package lambda;

/**
 * @author 葡萄
 * 基础语法测试-构造方法的引用
 */
public class LambdaTest04 {
    public static void main(String[] args) {
        //使用无参构造方法来引用
        ItemCreatorBlankConstruct construct = () -> new Item();
        Item item1 = construct.getItem();
        System.out.println(item1);

        ItemCreatorBlankConstruct construct2 =  Item::new;
        Item item2 = construct2.getItem();
        System.out.println(item2);

        //有参的构造方法
        ItemCreatorParamConstruct construct3 = Item::new;
        Item item3 = construct3.getItem(1,"葡萄",100);
        System.out.println(item3.name);

    }
}

public class Item {
    int id;
    String name;
    double price;
    public Item(int id,String name,double price){
        this.id = id;
        this.name = name;
        this.price = price;
    }
    public Item(){

    }
}

interface ItemCreatorBlankConstruct{
    Item getItem();
}

interface ItemCreatorParamConstruct{
    Item getItem(int id,String name,double price);
}

7.3Lambda表达式创建线程

我们以往都是通过Thread对象,然后通过匿名内部类重写run()方法,一提到匿名内部类我们就应该想到可以使用lambda表达式来简化线程的创建过程。

package lambda;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 葡萄
 * 基础语法测试-创建线程对象
 */
public class LambdaTest05 {
    public static void main(String[] args) {
        //Runnable
        new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("ok");
                    }
                }
        ).start();

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

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


        ExecutorService executorService = Executors.newCachedThreadPool();
        //Runnable
        executorService.submit(()->{
            System.out.println("我是runnable的接口实现");
        });
        //Callable
        executorService.submit(()->{
            return "完成";
        });
        executorService.submit(()->"完成");
    }
}

7.4Lambda遍历集合

我们可以调用集合的public void forEach(Consumer<? super E> action)方法,通过lambda表达式的方式遍历集合中的元素。以下是Consumer接口的方法以及遍历集合的操作。Consumer接口是jdk为我们提供的一个函数式接口。

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    //...
}
  • Lambda遍历简单集合
package lambda;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author 葡萄
 * 基础语法测试-遍历简单集合
 */
public class LambdaTest06 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
//        List<Integer> integerList = new ArrayList<>();
//        integerList.add(1);
//        integerList.add(2);
//        integerList.add(3);
//        integerList.add(4);
//        integerList.add(5);
//        integerList.add(6);
        for (Integer integer : list) {
            System.out.print(integer+"\t");
        }
        System.out.println();
        System.out.println("------");
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+"\t");
        }
        System.out.println();
        System.out.println("------");
        //lambda的遍历
        list.forEach((t)->{
            System.out.print(t+"\t");
        });
        System.out.println();
        System.out.println("------");
        list.forEach(t->{
            System.out.print(t+"\t");
        });
        System.out.println();
        System.out.println("------");
        list.forEach(t->System.out.print(t+"\t"));
        System.out.println();
        System.out.println("------");
        list.forEach(System.out::print);

    }
}
  • Lambda遍历复杂集合
package lambda;


import java.util.ArrayList;
import java.util.List;

/**
 * @author 葡萄
 * 基础语法测试-遍历复杂集合
 */
public class LambdaTest07 {
    public static void main(String[] args) {
        List<Item> itemList = new ArrayList<>();
        itemList.add(new Item(1,"饺子",10.00));
        itemList.add(new Item(2,"汤圆",5.22));
        itemList.add(new Item(3,"奶茶",20.56));
        itemList.add(new Item(4,"布丁",22.33));
        itemList.add(new Item(5,"芋圆",16.05));

        //以前的遍历方法
        for (int i = 0; i < itemList.size(); i++) {
            System.out.println(itemList.get(i)+"\t");
        }
        for (Item item : itemList) {
            System.out.println(item);
        }

        System.out.println("---------");

        //使用lambda表达式遍历
        itemList.forEach(item -> System.out.println(item));
        System.out.println("---------");
        itemList.forEach(item -> System.out.println(item.getName()));
        System.out.println("---------");
        itemList.forEach(System.out::println);

    }
}

其中的Item类如下

package lambda;

public class Item {
    int id;
    String name;
    double price;
    public Item(int id,String name,double price){
        this.id = id;
        this.name = name;
        this.price = price;
    }
    public Item(){

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Item{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

7.5删除集合中的某个元素

我们通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,Predicate也是jdk为我们提供的一个函数式接口,可以简化程序的编写。

package lambda;


import java.util.ArrayList;
import java.util.List;

/**
 * @author 葡萄
 * 基础语法测试-集合元素删除
 */
public class LambdaTest08 {
    public static void main(String[] args) {
        List<Item> itemList = new ArrayList<>();
        itemList.add(new Item(1,"饺子",10.00));
        itemList.add(new Item(2,"汤圆",5.22));
        itemList.add(new Item(3,"奶茶",20.56));
        itemList.add(new Item(4,"布丁",22.33));
        itemList.add(new Item(5,"芋圆",16.05));

        itemList.forEach(System.out::println);
        System.out.println("---------");

        //删除id=2的元素
        for (Item item : itemList) {
            if (item.getId()==2){
                itemList.remove(item);
                break;
            }
        }

        itemList.forEach(System.out::println);
        System.out.println("---------");

        //使用lambda移除id=5
        itemList.removeIf(item -> item.getId()==5);
        itemList.forEach(System.out::println);
        System.out.println("---------");
    }
}

7.6集合内元素的排序

在以前我们若要为集合内的元素排序,就必须调用sort方法。传入比较器匿名内部类重写compare方法,我们现在可以使用lambda表达式来简化代码。

package lambda;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author 葡萄
 * 基础语法测试-集合元素排序
 */
public class LambdaTest09 {
    public static void main(String[] args) {
        List<Item> itemList = new ArrayList<>();
        itemList.add(new Item(1,"饺子",10.00));
        itemList.add(new Item(2,"汤圆",5.22));
        itemList.add(new Item(3,"奶茶",20.56));
        itemList.add(new Item(4,"布丁",22.33));
        itemList.add(new Item(5,"芋圆",16.05));

        itemList.forEach(System.out::println);
        System.out.println("---------");

//        Collections.sort(itemList, new Comparator<Item>() {
//            @Override
//            public int compare(Item o1, Item o2) {
//                return (int) (o1.getPrice()- o2.getPrice());
//            }
//        });
//        Collections.sort(itemList,(o1,o2)->{
//            return (int) (o1.getPrice()- o2.getPrice());
//        });
        Collections.sort(itemList, (o1,o2)->(int) (o1.getPrice()- o2.getPrice()));
        itemList.forEach(System.out::println);
        System.out.println("---------");

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值