Java笔记 —— lambda

先来看用普通的方法来完成集合的筛选,不用匿名内部类和lambda表达式
在这里插入图片描述
用测试类的方式来测试代码
如何使用这种测试类来测试代码,看这篇博客

@Test
    public void show1(){
        List<Student> list1 = filterStudentAge(list);
        for(Student s:list1){
            System.out.println(s);
        }

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

        List<Student> list2 = filterStudentScore(list);
        for(Student s : list2){
            System.out.println(s);
        }
    }

    public List<Student> filterStudentAge(List<Student> list){
        //找出所有年龄超过30岁的学生
        List<Student> list1 = new ArrayList<Student>();
        for(Student s : list){
            if(s.getAge()>30){
                list1.add(s);
            }
        }
        return list1;
    }

    public List<Student> filterStudentScore(List<Student> list){
        //找出所有成绩大于50分的学生
        List<Student> list1 = new ArrayList<Student>();
        for(Student s : list){
            if(s.getScore()>50){
                list1.add(s);
            }
        }
        return list1;
    }

运行测试show方法后
在这里插入图片描述
完成了年龄的筛选,选出了年龄大于30的学生对象
完成了成绩的筛选,选出了成绩大于50的学生对象

方式二,用接口的方式,将判断集合是否满足某个条件,这个功能放入接口中。再用不同的具体实现类实现不同的筛选条件

接口

package lambdaDemo;

public interface filterInterface<Student> {
    public boolean judge(Student s);
}

实现接口的类

package lambdaDemo;

public class filterStudentByAge implements filterInterface<Student> {
    public boolean judge(Student s) {
        return s.getAge() > 30;
    }
}

package lambdaDemo;

public class filterStudentByScore implements filterInterface<Student>{

    public boolean judge(Student s) {
        return s.getScore()>50;
    }
}

具体的方法和测试方法

//将实现类作为参数传进方法中,然后里面实现类中的方法完成筛选
public List<Student> filterStudent(List<Student> list, filterInterface<Student> f){
        List<Student> list1 = new ArrayList<Student>();
        for(Student s : list){
            if(f.judge(s)){
                list1.add(s);
            }
        }
        return list1;
    }

//测试方法
    @Test
    public void show2(){
        List<Student> list1 = filterStudent(list,new filterStudentByAge());
        for(Student s : list1){
            System.out.println(s);
        }

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

        List<Student> list2 = filterStudent(list,new filterStudentByScore());
        for(Student s : list2){
            System.out.println(s);
        }
    }

在这里插入图片描述
这样写的好处是只要一个方法,实现不同的功能可以靠不同的实现类
但是这样写要实现的类太多

这里用到了策略设计模式
方法括号里面写接口引用变量,实际传入 实现类 的对象
给方法什么策略,就按什么过滤,策略是按年龄筛选,实际方法中就按年龄筛选

方式三、匿名内部类

//具体实现筛选的类,接口的实现类将作为参数传入这个方法,引用变量f调用实现类的方法
public List<Student> filterStudent2(List<Student> list,filterInterface<Student> f){
        List<Student> list1 = new ArrayList<Student>();
        for(Student s : list){
            if(f.judge(s)){
                list1.add(s);
            }
        }
        return list1;
    }


//不需要新建实现类来实现接口功能
//在传入参数的时候,用匿名内部类的方式写实现类
    @Test
    public void show3(){
        List<Student> list1 = filterStudent2(list, new filterInterface<Student>() {
            public boolean judge(Student s){
                return s.getAge()>40;
            }
        });

        for(Student s : list1){
            System.out.println(s);
        }

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

        List<Student> list2 = filterStudent2(list, new filterInterface<Student>() {
            public boolean judge(Student s) {
                return s.getScore()>50;
            }
        });
        for(Student s : list2){
            System.out.println(s);
        }
    }

方式二接口中的filterStudent方法与方式三匿名内部类的filterStudent2方法内容一样
只不过为了方便看,又写了这个filterStudent2方法
下面的方式四、lambda表达式,就不再重复写这个方法了,直接用方式二中的filterStudent方法

方式四、lambda

    @Test
    public void show4(){
        List<Student> list1 = filterStudent(list , (e) -> e.getAge()>30);
        list1.forEach(System.out::println);
    }

在这里插入图片描述
什么都不需要,接口和具体类都不用,只要这两行代码,就可以完成之前的所有任务

lambda语法的基本格式

Java8中引入了一个新的操作符“->",该操作符称为箭头操作符或者Lambda操作符
箭头操作符将Lambda表达式拆分成两部分
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能,即lambda体

lambda表达式 (e) -> e.getAge()>30 实际上是对之前的接口的具体实现

public interface filterInterface<Student> {
    public boolean judge(Student s);
}

我们原先使用匿名内部类实现这个接口,现在可以用lambda表达式的方式来实现
箭头操作符的左侧,也就是(e)对应的是接口的抽象方法中的参数列表(Student s),有几个参数,lambda括号中的参数就有几个

箭头操作符的右侧,e.getAge()>30 写的是接口抽象方法的具体实现

注意lambda只适用于函数式接口,接口里面有且仅有一个抽象方法

可以使用注解@FunctionalInterface修饰,这个修饰的作用是,检查是否是函数式接口

@FunctionalInterface
public interface test1 {
    public void show();
}

此时如果多写一个抽象方法,就会提示错误

lambda表达式的语法格式
语法格式一:无参数,无返回值

左侧无参就直接写小括号

这是接口

package lambdaDemo1;

public interface test1 {
    public void show();
}

分别用匿名内部类与lambda表达式来实现接口

package lambdaDemo1;

import org.junit.Test;

public class demo1 {
    @Test
    public void method1(){
        //用匿名内部类来实现接口
        test1 t = new test1() {
            @Override
            public void show() {
                System.out.println("匿名内部类的show");
            }
        };
        t.show();

        System.out.println("================");
        //用lambda表达式来实现接口
        test1 t1 = () -> System.out.println("lambda表达式的show");
        t1.show();
    }
}

结果为
在这里插入图片描述
这里对象 t 和 t1 都能调用接口里面的抽象方法show,是因为匿名内部类和lambda实质上都是对这个接口的具体实现。
lambda是将一个实现接口的具体类浓缩为了一句表达式,这句表达式就是接口的show方法的重写实现

() -> System.out.println(“lambda表达式的show”);
public void show();
箭头操作符的左侧(), 对应show()的参数列表()

箭头操作符的右侧System.out.println(“lambda表达式的show”);
相当于这个方法的方法体

public void show(){
	System.out.println("lambda表达式的show");
	}

注意

package lambdaDemo1;

import org.junit.Test;

public class demo1 {
    @Test
    public void method1(){
        int num = 10;
        
        //匿名内部类可以调用同级别的局部变量
        //lambda也可以调用,不过和匿名内部类一样,这个局部变量是final修饰的,无法改变
        test1 t2 = () -> System.out.println("lambda"+num);
        t2.show();
    }
}

语法格式二,有一个参数,并且无返回值

之前Student类的例子就是这个,这里就不再举例了

语法格式三,有两个参数,有返回值,并且lambda体中有多条语句

如果要使用多条语句,那么lambda体必须要有大括号

package lambdaDemo1;

public interface test2 {
    public boolean compare(int a,int b);
}

package lambdaDemo1;

import org.junit.Test;

public class demo2 {
    @Test
    public void method(){
        test2 t = (x,y) -> {
            System.out.println("x与y比较大小");
            return x>y ? true : false;
        };
        boolean b = t.compare(3,2);
        System.out.println(b);
    }
}

在这里插入图片描述

语法格式四,有两个参数,有返回值,并且lambda体中只有一条语句

此时,lambda表达式中的大括号和return关键词都可以省略
上面的那个数字比较的lambda表达式例子就可以简写为

@Test
    public void method2(){
        test2 t = (x,y) -> x>y ? true : false;
        System.out.println(t.compare(4,2));
    }

在这里插入图片描述

语法格式五,lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”

例子就用上面的(x,y)即可,这里的x与y都没有定义数据类型

实例运用

需求:对一个数进行运算
步骤:

  1. 写一个接口,接口的抽象方法接收一个数字,并且返回一个数字
public interface test3 {
    public Integer getValue(Integer i);
}
  1. 写一个方法,这个方法要对数字进行运算
    如果直接写public Integer operation(Integer num),这样写就等于锁死了数字的处理方式,每进行一种操作,就需要写一个方法。比如方法体是这个num再加上一个数,如果想换成减去一个数,就又要写一个新的方法,因此要加进去刚才写的接口
public Integer operation(Integer num, test3 t){
        return t.getValue(num);
    }
  1. 这里虽然用上了接口,但是具体做什么运算没有指定,现在就需要再写一个新的方法,方法中调用operation方法,并且用lambda表达式实现接口的具体功能
@Test
    public void method(){
        //完成平方操作
        Integer i = operation(10,(x) -> x*x);
        System.out.println(i);

    }

在这里插入图片描述
这里也可以通过更改lambda表达式的方式,来修改具体实现的运算功能

@Test
    public void method(){
        //完成平方操作
        Integer i = operation(10,(x) -> x*x);
        System.out.println(i);

        //将这个数加上100
        System.out.println(operation(20,(y) -> y+100));

    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一纸春秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值