Java8之Lambda表达式使用解读

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Java8之Lambda表达式使用解读

代码大师麦克劳瑞   2022-11-22 我要评论

一、初识Lambda

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

这是来自万能的百度百科对于lambda表达式的解释,懂的都懂,不懂的真是听君一席话,如听一席话。

Lambda表达式在Java8中及后续版本占据了举足轻重的地位,对于函数式编程来说是必不可少的一环,所以学会lambda表达式,对于使用Java8的同学是必经之路

举个栗子,Java8中的stream你们不会没有用过吧?什么?你还在用Java7?阿巴阿巴阿巴…好吧,那我直接用代码举个栗子吧。

1.Lambda栗子

需求是这样的,二哥第一次来到了大城市,到了大城市就去了 大 保 健,这个时候肯定就要选女朋友了,根据姓名、大小、价位等,咳咳咳…说错了,是根据姓名、鞋码、身价来选择,二哥要求经理让这些女朋友按照身价来正序排队站好。

@Data
@AllArgsConstructor
public class Girl {

    private String name;

    private Double size;

    private Double price;
}
    public static void main(String[] args) {
         ArrayList<Girl> list = Lists.newArrayList();
        list.add(new Girl("露西",33d,2000d));
        list.add(new Girl("格蕾丝",36d,3000d));
        list.add(new Girl("安娜",28d,1500d));
        list.add(new Girl("克瑞斯",31d,1800d));
        //匿名函数类实现
        list.sort(new Comparator<Girl>() {
            @Override
            public int compare(Girl o1, Girl o2) {
                return o1.getPrice().compareTo(o2.getPrice());
            }
        });
        list.stream().forEach(System.out::println);

        Collections.shuffle(list);
        System.out.println("-------------我是分隔符-----------------");

        //lambda实现
        list.sort((Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice()));
        list.stream().forEach(System.out::println);
    }

不难看出,两种方式都实现了让女朋友们按照身价排队。那么我们着重来看看Lambda表达式。

2.Lambda表达式的组成

(Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice());
  • 参数列表:本例中是两个Mask对象的参数,采用的是Comparator接口中compare方法的参数。
  • 箭头:->把参数列表和主体分隔为两个部分。
  • 主体:本例中是把比较价格的表达式作为Lambda表达式的返回。主体可以修改成另外一种写法,含义是一样的:
list.sort((Girl g1, Girl g2)-> {
	return g1.getPrice().compareTo(g2.getPrice());
});

由此可以看出,lambda表达式语法格式可以分为两种:

  • 1.(parameters) -> expression //参数列表加单条表达式
  • 2.(parameters) ->{ statements; } //参数列表加花括号和多条语句

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

3.举个栗子

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

// 6.接受两个int参数,多条语句进行比较返回1或者0
(int s1, int s2)->{
	if(s1>s2){
		return 0;
	}
	return 1;
}

二、Lambda更进一步

1.类型推断

 	  //lambda实现
      list.sort((Girl g1, Girl g2)-> g1.getPrice().compareTo(g2.getPrice()));

      //lambda简化写法
      list.sort((g1, g2)-> g1.getPrice().compareTo(g2.getPrice()));

2.方法引用

方法引用通过方法的名字来指向一个方法。方法引用可以使语言的构造更紧凑简洁,减少冗余代码。方法引用使用一对冒号 :: 。

Comparator<Girl> comparator = (g1, g2)-> g1.getPrice().compareTo(g2.getPrice());
//方法引用
Comparator.comparing(Girl::getPrice);

当你需要方法引用时,目标引用放在分隔符::前,方法的名称放在分隔符::后。

比如,上面的Girl::getPrice,就是引用了Mask中定义的getPrice方法。

方法名称后不需要加括号,因为我们并没有实际调用它。

方法引用提高了代码的可读性,也使逻辑更加清晰,在一些stream流中,相信大家也经常会用到。

例如:

 List<String> collect = list.stream().map(Girl::getName).collect(Collectors.toList());
 list.stream().forEach(System.out::println);

我们看到第一行通过Girl::getName方法引用,我们收集到了所有女孩的名字,那么第二行我们通过System.out::println打印出了list中的所有对象。

举个栗子:

我们先改造一下实体类,增加了空参构造函数,增加了几个方法,有静态方法和非静态方法。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Girl {

    private String name;

    private Double size;

    private Double price;


    //Supplier是jdk1.8的接口,这里和lamda一起使用了
    public static Girl create(final Supplier<Girl> supplier) {
        return supplier.get();
    }

    public static void makeUp(final Girl girl) {
        System.out.println("化妆  " + girl.toString());
    }

    public void follow(final Girl another) {
        System.out.println("Following the " + another.toString());
    }

    public void dressUp() {
        System.out.println("更衣 " + this.toString());
    }
}

4种不同的方法引用

	  //构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
       Girl girl = Girl.create(Girl::new);
       List<Girl> girls = Arrays.asList(girl);

       //静态方法引用:它的语法是Class::static_method,实例如下:
       girls.forEach(Girl::makeUp);

       //特定类的任意对象的方法引用:它的语法是Class::method实例如下:
       girls.forEach(Girl::dressUp);

       //特定对象的方法引用:它的语法是instance::method实例如下:
       girls.forEach(girl::follow);

到这里,大家对lambda表达式应该有了初步的认识,可以在平时编码中多使用,毕竟实践出真知!!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们