< Java SE>速通 Lamdba表达式

Lamdba表达式

Lamdba表达式由JavaSE8提供,它允许我们把函数作为一个方法的参数传入,可以认为是匿名内部类(类限定为函数式接口)的简化形式,能够帮助我们简化代码,优化代码结构,lamdba表达式也称之为闭包

基本语法:

(参数列表) ->{方法体 }

(parameters) -> expression 或 (parameters) ->{ statements; }

①参数列表:即函数式接口的形参列表,类型可不声明,括号可省略

②->:lamdba表达式的固定语法,用于链接参数列表和表达式主体,可以理解为“被用于”的意思

③方法体:重写方法的具体实现,可以是表达式或是代码块,当为单个语句(表达式)时{}可省略

interface and {//函数式接口,仅有一个抽象方法的接口
    void setAnd(int a, int b);
}
public class Test1 {
    public static void main(String[] args) {
        //匿名内部类方式
        and testA = new and() {
            @Override
            public void setAnd(int a, int b) {
                System.out.println(a+b);
            }
        };

        //lamdba方式
        and testB = (c,d) -> System.out.println(c+d);

        //测试
        testA.setAnd(1, 3);
        testB.setAnd(1,3);
    }
}

Lamdba简化规则

1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。

and testB = (int c, int d) -> System.out.println(c+d);
and testB = (c,d) -> System.out.println(c+d);

2. 参数的小括号里面只有一个参数,那么小括号可以省略

and testc = (c) -> System.out.println(c);
and testc = c -> System.out.println(c);

3. 如果方法体当中只有一句代码,那么大括号可以省略

and testB = (c,d) -> {System.out.println(c+d);};
and testB = (c,d) -> System.out.println(c+d);

4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字

aff testF = (c,d) -> {return c+d;};
aff testF = (c,d) -> c+d;

Lamdba变量的捕获

Lamdba表达式和匿名内部类一样都可以访问封闭类内的成员,即在lamdba表达式内同样可以使用部分封闭类的变量和参数

注意的是可捕获的变量包括final修饰的变量,或是未被修改过的变量。

interface and {//函数式接口,仅有一个方法的接口
    void setAnd(int a, int b);
}
public class Test1 {
    public static void main(String[] args) {
        //final修饰的变量
        final int a = 10;
        //lamdba方式,可调用fianl修饰的变量a
        and testB = (c,d) -> System.out.println(c+d+a);

        testB.setAnd(1,3);
    }
}

public class Test1 {
    //未被修改过的成员变量
    public int s = 20;
    public void text() {
        and testB = (c,d) -> System.out.println(c+d+s);
    }
    public static void main(String[] args) {
        //未被修改过的
        int a = 10;
        //lamdba方式,可调用fianl修饰的变量a
        and testB = (c,d) -> System.out.println(c+d+a);

        testB.setAnd(1,3);
    }
}

Lamdba与接口

为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口和方法,以便与Lambda表达式对接(很多,仅列举集合框架相关常用)

1.collection接口forEach()方法

collection接口是Java集合框架的一个顶层接口,提供的forEach()方法可以用来对集合类中的每个元素进行遍历并进行相应的操作,源码如下:

//对每个元素执行action.accept()操作
default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

在源码中可以看到action类作为forEach()方法的形参对集合类的每个元素都执行了accept()方法,而action是一个函数式接口,是可以使用Lamadba表达式的。

forEach方法的作用就显而易见了,例如可以通过Lamdba表达式重写action的accept方法来对集合类进行遍历输出。

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.forEach( a -> System.out.print(a) );

其他用法比一一赘述,请自行摸索

2.List接口sort方法

List接口提供的sort方法可以根据我们提供的排序规则对集合类进行排序,源码如下:

public void sort(Comparator<? super E> c) {
    final int expectedModCount = modCount;
    Arrays.sort((E[]) elementData, 0, size, c);
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
    modCount++;
}

排序的比较方法是返回正负值判断的大小,如a、b两个参数a-b>0则认为a>b

对于逆序排序我们可以这样写:

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.sort((a,b) -> b-a);
        list.forEach(a -> System.out.print(a));

对于字符串根据长短排序我们可以这样写:

        List<String> list = new ArrayList<>();
        list.add("buffer");
        list.add("hello");
        list.add("bet");
        list.add("As");
        list.sort((a,b) -> a.length()-b.length());
        list.forEach(a -> System.out.println(a));

3.Map接口与forEach

和Collection接口的forEach方法类似,同样是对Map中每个映射执行action.accept()方法,源码如下:

default void forEach(BiConsumer<? super K, ? super V> action) {
    Objects.requireNonNull(action);
    for (Map.Entry<K, V> entry : entrySet()) {
        K k;
        V v;
        try {
            k = entry.getKey();
            v = entry.getValue();
        } catch(IllegalStateException ise) {
            // this usually means the entry is no longer in the map.
            throw new ConcurrentModificationException(ise);
        } 
        action.accept(k, v);
    }
}

可以实现对输出每个映射:

        Map<String, Integer> map = new HashMap<>();
        map.put("1",1);
        map.put("2",2);
        map.put("3",3);
        map.put("4",4);
        map.put("5",1);
        map.forEach((a,b) -> System.out.println(a + "=" + b));

函数式接口

函数式接口:在Java中指一个接口中仅有一个抽象方法的接口。(default修饰的方法不包含在内,可以和抽象方法并存,lamdba不会报错)

interface and {//函数式接口,仅有一个方法的接口
    void setAnd(int a, int b);
}

如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的

@FunctionalInterface
interface and {//函数式接口,仅有一个方法的接口
    void setAnd(int a, int b);
    default void test() {
        System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");
    }
}

博主是Java新人,每位同志的支持都会给博主莫大的动力,如果有任何疑问,或者发现了任何错误,都欢迎大家在评论区交流“ψ(`∇´)ψ

优雅美丽的Lamdba----

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值