Lambda

Lambda表达式

##介绍
Lambda表达式是JDK1.8的新增的重要特性,它可以极大地简化代码,使得代码更为简洁。
对于接口的实现我们有两种方式,一种是接口实现类,另一种就是匿名内部类的方式对接口作实现。lambda表达式本质上也是一个匿名内部类,常用于实现某个接口,这可以取代大部分匿名内部类。lambda表达式可以使代码更加优雅简洁,尤其是在集合的操作中可以大大优化代码结构。但要注意的是,lambda表达式实现的是函数式接口,(函数式接口就是指只有一个函数需要被实现的接口);
加上注解:@FunctionalInterface的接口就是一个函数式接口

lambda表达式语法

lambda语法结构如下:
(参数列表)->{实现函数};//因为能实现的方法只有一个,所以要求是一个函数式接口;

实例

	//定义一个接口:
@FunctionalInterface
interface Test{
    void method();
}
public class Test {
    public static void main(String[] args) {
    		Test test =()->{System.out.println("Test");}
    		test.method();//结果为:Test
    }
}

如果不是用Lambda表达式,则代码需要这样写:

public class Test {
    public static void main(String[] args) {
    		Test test = new Test(){
    			public void method(){
    				System.out.println("Test");
    			}
    		}
    		test.method();//结果为:Test
    }
}

由此可体会到lambda表达式带来的简洁性,与优雅性。

lambda表达式的简化

对于函数体只有一句的实现方法可以省略大括号;参数的类型可以省略,因为JVM会自动识别;
对于没有参数没有返回值的实现方法:()->{};
对于有一个参数的无返回值的实现方法:小括号可以省略,如:a->{};
对于有多个参数,无返回值情况:小括号不可以省略:(a,b)->{};
对于无参数,有返回值情况:()->{};//返回值类型省略
对于有一个参数,有返回值:a->{};
对于有多个参数,无返回值情况不能省略;

package Lamada;

/**
 *无返回值,无参数;
 */
@FunctionalInterface
interface NoReturnNoPaten{
    void method();
}
/**
 *无返回值,一个参数
 */
@FunctionalInterface
interface NoReturnOneParen{
    void method(int i);
}

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

/**
 * 有返回值,无参数;
 */
@FunctionalInterface
interface ReturnNoParen{
    int method();
}
/**
 * 有返回值,有一个参数
 */
@FunctionalInterface
interface ReturnOneParen{
    int method(int i);
}
/**
 * 有返回值,有多个参数;
 */
@FunctionalInterface
interface ReturnManyParen{
    int method(int a,int b);
}
public class Test {
    public static void main(String[] args) {
        //完整版本
        NoReturnNoPaten noReturnNoPaten=()->{System.out.println("无参数无返回值");};//简化:()->System.out.print;
        noReturnNoPaten.method();
        NoReturnOneParen noReturnOneParen = (int a)->{System.out.println("有一个参数无返回值");};//a->...;
        noReturnOneParen.method(1);
        NoReturnManyParen noReturnManyParen = (int a,int b)->{System.out.println("有多个参数无返回值");};//(a,b)->...;
        noReturnManyParen.method(1,2);
        ReturnNoParen returnNoParen = ()->{System.out.println("没有参数有返回值");return 1;};//()->{};
        returnNoParen.method();
        ReturnOneParen returnOneParen = (int a)->{System.out.println("有返回值有多个参数");return a;};//a->{};
        returnOneParen.method(1);
        ReturnManyParen returnManyParen = (int a,int b)->{System.out.println("有多个返回和多个参数");return a+b;};//(a,b)->{};
        returnManyParen.method(1,2);
    }
}

lambda表达式_引用方法

有时候我们不一定要使用lambda表达式对函数进行实现,可以利用lambda表达式指向一个已经被实现好的方法;

语法:
方法归属者::方法名
其中,静态方法的归属者为类名,普通方法的归属者为类对象;

public class Test2 {
    public static void main(String[] args) {
        ReturnOneParen returnOneParen = a->Do(a);//在本类中实现,或者使用Test2::Do;
        returnOneParen.method(10);
        ReturnOneParen returnOneParen1 = Test::Do2;//在另一个类(Test类)中实现
        //对于非静态的方法,则需要使用该类的一个对象即 test::Double2(double2是非静态方法);
        returnOneParen.method(10);
    }
    public static int Do(int a){
        return a;
    }
}
//Test类:
public class Test {
    public static void main(String[] args) {
    }
    public static int Do2(int a){
        return a;
    }
}

lambda表达式在线程中的使用:

线程的创建方式有两种,一种是继承thread类,一种是实现Runable接口,并实现run()方法;
lambda表达式可以用于替代Runable接口这种创建方法,因为lambda本质上就是来替代函数式接口实现类的,而Runale恰好就是一个函数式接口;

public class Test3 {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"开始");
        new Thread(()->{ 	  	     	 System.out.println(Thread.currentThread().getName()+"balabal");},"Lamada").start();
        System.out.println(Thread.currentThread().getName()+"结束");
    }
}

lambda操作集合

遍历集合:

//我们可以通过调用集合的public void forEach (Consumer<? super E>action)方法,通过lambda表达式的方式遍历集合中的元素。Consumer接口是JDK提供的一个函数式接口;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 自己定义接口的方式;
 */
class ConsumerInput implements Consumer{
    @Override
    public void accept(Object o){
        System.out.println(o);
    }
}

public class Test4 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        ConsumerInput c=new ConsumerInput();//这是自己定义接口的方式
        list.forEach(System.out::println);//lambda表达式的形式
    }
}

删除结合中的元素

//我们可以通过public boolean void removeIf(Predicate<? super E>filter)方法来删除集合中的元素;Predicate是jdk提供的一个函数式接口;

public class Test5 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        //删除b元素
        list.removeIf(ele->{ele.equals("b");});//lambda表达式的形式,ele为参数
    }
}

对集合中的元素进行排序;

public class Test6 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.sort((o1,o2)->{
            return o1.compareTo(o2);
        });
    }
}

补充:

注意

lambda表达式中访问的局部变量,只能是常量类型,在后续中如果对被访问的局部变量进行修改编译器会报错,这是因为匿名内部类中的局部变量只能是常量类型;
为什么局部变量不能而静态变量可以,存在于栈中,不能被不同的线程共享,而静态变量存在于堆中,是可以被共享的,不同的线程可以访问该变量。

匿名内部类;

对于匿名内部类,匿名指没有名字,也不用class关键字的类,内部,指在一个类中定义的类,一般只用一次。匿名内部类其多用做创建某个接口类型的对象时使用。
其语法结构如下:
new 父类构造器(参数类标或者实现接口){
//主体部分;
}

- [百战程序员] 高琪Java300集
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值