Java基础之初见Lambda表达式

目录

一、前言

二、Lambda表达式语法

无参函数的写法

含参表达式:

三、Lambda表达式的语法糖

引用对象方法:

类方法引用: 

构造器引用:

四、函数式接口:

 



一、前言

Lambda表达式是Java8中最瞩目的新特性之一,Lambda表达式描述的是一个代码块或者称为匿名方法,可以将其作为参数传递给构造方法和或者普通方法以便后续执行。为了简便代码块的使用,最直观的应该就是简化匿名内部类的使用。

二、Lambda表达式语法

体验一下:A是一个接口,还有一个add方法,B是一个实体类,需求是B需要实现调用A的方法,N多年的实现方式可以通过实现这个类而重写这个方法或者通过匿名内部类,现在只需要通过Lambda表达式的三行代码就可以完成实现这个需求,Lambda表达式的简洁语法一定会给你留下深刻的印象。

  A接口
  public interface A {
      public abstract void  add();
       
}
  B类
  public class B {
    
   public B(A a){

    }

}
测试类
    public static void main(String[] args) {
        //1.Lambda
       new B(() -> {
            System.out.print("Lambda1");
          
        });
        //2.匿名内部类
        new B(new A() {
            @Override
            public void add() {
                System.out.print("anonymous");
            }
        });
    }

Lambda使用的一个重要依据必须存在函数接口,上面的例子只是无参的一种写法,Lambda表达式的编写方法还有很多种:

无参函数的写法

无参表达式:

1.当只有一行计算的计算的时候Lambda可以无需大括号{}
例:
   () -> System.out.print("Lambda1" + "\n");

(),->  表达式

2.当计算方法无法房子一个表达式时可以将代码块放在{}中
例:
   () -> {
       System.out.print("Lambda1" + "\n");
       System.out.print("Lambda2" + "\n");
    };


示例: 

    public static void main(String[] args) {
        //Java1.8以前的写法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Java1.7");
            }
        }).start();

        //Java1.8 Lambda表达式
        new Thread(() ->System.out.print("Runnable")).start();
    }

含参表达式:

上面的类子只是无参的一种写法,Lambda表达式的编写方法还有很多种: 

含参函数:

一、单个参数

(参数类型 参数)->  表达式

 1.表达式
  (String a) ->  System.out.print(a);
 2.代码块
  (String a) ->{
    System.out.print(a)
    System.out.print(a)
  };

Labbda表达式可以根据上下文推断出参数类型,所以还可以省去参数类型(不建议这种编写方式,使代码的可读性差)

(参数)->  表达式

(a) ->  System.out.print(a);


二、多个参数

(参数类型1 参数1,参数类型2,参数2)->  表达式

 (String a,String b) ->{
    System.out.print(a)
    System.out.print(b)
  };

当多参函数只有一条表示式时也可以简写:

 (String a,String b) -> System.out.print(a+b);


Lambda表达式甚至还可以省略参数:

(引用类型::函数方法)

  示例:

//Comparator接口
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}

//安装从大到下排序集合的元素
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(3, 1, 2);
        List<Integer> list2 = Arrays.asList(1, 3, 2);
        List<Integer> list3 = Arrays.asList(3, 2, 1);
        //Java1.8之前的写法
        Collections.sort(list1, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
        System.out.print(list1 + "\n");

        //Lambda表达式
        Collections.sort(list2, (Integer o1, Integer o2) -> {
            return o1.compareTo(o2);
        });
       
        //还可以把参数类型和return省略
        Collections.sort(list2, (o1,o2)->o1.compareTo(o2));
        System.out.print(list2 + "\n");

        //Lambda表达式更简化的写法,省略参数
        Collections.sort(list3, Integer::compareTo);
        System.out.print(list3);
    }

打印结果:
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]

关于变量:

  • Lambda表达式中的变量是最终变量,在变量初始化之后就不会再为它赋新值,而如果变量是动态可变的,将不被允许(比如for循环中i);
  • 因为Lambda表达式和匿名内部类作用域是一样的,所有不能有同名的局部变量;
  • 在This关键字是指的当前类,而不是函数接口;

 

三、Lambda表达式的语法糖

在Lamdba的的梳理方法中,看到了(引用类型::函数方法)的写法,可能都会这种语法比较疑惑,这种写法其实是Java的一个语法糖,有时已经可能有线程的方法可以完成传递代码的工作,这种语法糖的编写方式使代码变得更加简洁,对于引用的方法,主要有四种:

  • 对象方法
  • 静态方法
  • 类方法
  • 构造器

引用对象方法:

当调用表达式可以通过对象引用::对象方法d的方式表示:

语法:
   
   对象引用::对象方法
示例:

//接口
interface  MethodRef{
    void test(int b);
}

public class Test01 {
    public static void main(String[] args) {

        //传统内部类
        MethodRef mr1 = new MethodRef() {
            @Override
            public void test(String s1) {
                System.out.println(s1);
            }
        };
        mr1.test("传统内部类");

        //Lambda传统写法
        MethodRef mr2 =(s2) -> System.out.println(s2);
        mr2.test("Lambda传统写法");

        //Lambad引用对象方法
        MethodRef mr3 = System.out::println;
        mr3.test("Lambad引用对象方法");
    }
}
输出:
传统内部类
Lambda传统写法
Lambad引用对象方法

-----------------------------------------------------------
System.out对应的是PrintStream
当调用本身类方法是对象引用还是修改为this

引用静态方法:

当调用方法为静态方法时,可以使用 类名::静态方法的方式

语法:
   
   类名::静态方法

示例:

//实现工具类
public class Until {

    public static int comare(Integer a,Integer b){
        return  a.compareTo(b);
    }
}

//测试类
public class Test02 {
    public static void main(String[] args) {

        //静态方法引用
        List<Integer> list1 = Arrays.asList(3, 1, 2);
        Collections.sort(list1, Until::comare);
        System.out.print(list1);

    }
}
输出:
[1, 2, 3]

类方法引用: 

当存在多个参数,且调用的方法是是第一个参数的实例方法,并且以后的参数能对应该方法的参数列表,那么还有一种更直接的方式

语法:
   
   类名::实例方法名

interface MethodRef2 {
    void test(String s1, String s2);
}

public static void main(String[] args) {
        //传统内部类
        MethodRef2 mr1 = new MethodRef2() {
            @Override
            public void test(String s1, String s2) {
                s1.compareToIgnoreCase(s2);
            }
        };
        mr1.test("a", "b");

        //Lambda传统写法
        MethodRef2 mr2 = (s1, s2) -> s1.compareToIgnoreCase(s2);

        mr2.test("1", "2");
        //Lambad引用类方法
        MethodRef2 mr3 = String::compareToIgnoreCase;
        mr3.test("1", "2");
    }
}


构造器引用:

调用构造器 

语法:

type ::new

//接口
interface MethodRef3 {
    F test(String str);
}

//F类
public class F {
    public  F(String str){
        System.out.println(str);
    }
}

//测试类
public class Test03 {

    public static void main(String[] args) {
        //传承内部类
        MethodRef3 mr1 = new MethodRef3() {
            @Override
            public F test(String str) {
                return new F(str);
            }
        };
        mr1.test("传承内部类初始化");

        //lambda简化写法
        MethodRef3 ms2 = F::new;
        F f = ms2.test("lambda简化写法初使化");

        //lambda传统写法
        MethodRef3 mr3 = (str) -> new F(str);
        mr3.test("lambda传统写法初始化");
    }

}


       在经过初步了解了Lambda的使用方法之后,Lambda简化了编程步骤,但是代码风格的转变和差异,也会让很多不了解的Lambda的表达式的对代码的不理解。其实最初的学习前期,可以通过类比Lambda和匿名内部类来加深印象。

四、初步了解函数式接口:

       对于只有一个抽象方法的接口,我们称为函数式接口(functional interface),当然部分接口也隐含着Object的公共方法。Java中提供了很多分装代码块的接口,如Comparator和Runnable。lambda表达式与这些接口都是兼容的。Java8中已经定义了很多常用的函数式接口,它们都放在java.util.function包下面,一般有以下常用的四大核心接口:

以上就是对Lambda表达式的一些最基础的了解,后续会针对函数式接口的实际应用再来学习学习。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值