Java8新特性之Lambda表达式

一、引入Lambda表达式的原因。
        在介绍Lambda表达式之前,我们先说一下为什么Java的设计师要设计Lambda表达式,在Java8中提出了一种思想“行为参数化”,行为参数化就是把方法当作一个参数来传递。我们现在多用的是值参数化。假如现在有一个需求,一个水果店有很多水果,我们要筛选出颜色为红色的水果,我们会写出一个方法1的方法;就是把一个颜色color值传递到方法里面去比较。我们现在要用“行为参数化”的思想写出一个方法2:。你觉得方法1好还是方法2好呢?如果需求永远就这么一个,那应该是方法1好,因为简便,但是需求会不断的变化,比如新增一个需求要绿色的水果,要重于150g的水果等等。你就必须复制很多个类似方法1的方法,但是方法2传递的是一个匿名类,心新增的方法都能满足,不需要复制黏贴新的方法了。因此从长远来看,是方法2比方法1好。但是它的调用很复杂,有没有简单的方式来进行调用呢?这就引入了Lambda表达式了。如方法3,很简便。

方法1:
public static List<Fruit> getFruitByColor(List<Fruit> list,String color){
        List<Fruit> fruitList = new ArrayList<>();
        for (Fruit fruit : list){
            if (color.equals(fruit.getColor())){
                fruitList.add(fruit);
            }
        }
        return fruitList;
    }

方法1调用	
List<Fruit> redFruitList = getFruitByColor(fruitList, "red");

方法2:
public static List<Fruit> getFruit(List<Fruit> list, Predicate<Fruit> p){
        List<Fruit> fruitList = new ArrayList<>();
        for (Fruit fruit : fruitList){
            if(p.test(fruit)){
                fruitList.add(fruit);
            }
        }
        return fruitList;
    }
	
方法2调用(匿名内部类)
 List<Fruit> redFruitList1 = getFruit(fruitList, new Predicate<Fruit>() {
            @Override
            public boolean test(Fruit fruit) {
                return "red".equals(fruit.getColor());
            }
        });

方法2调用(Lambda)
 getFruit(fruitList,(Fruit f) -> "red".equals(f.getColor()));

二、Lambda表达式语法
       Lambda表达式可以理解为一种匿名函数:它没有名称,但有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
    1:()->{};
    2:(String s)->{return s.length}
    3:(String s)-> s.length
    “->”前是参数列表,“->”后是函数主体,单行时不用带{},如3,返回一个字符串的长度。如果带括号的话需要显示的加"return",才能返回
     那Lambda在哪里使用呢?下面我们来介绍函数式接口?
三、函数式接口
    函数式接口就是只有一个抽象方法的接口。下面是自定义的函数式接口1,@FunctionalInterface可以不加,但是加了如果接口中不只有一个方法的话,就会编译出错。因此还是加上为好。下面写一个筛选水果的方法2,然后写一个调用这个方法2的方法3.在方法3中,我们可以 看到Labmda表达式的参数列表没有类型,对的Lambda表达式会根据上下文来判断参数的类型。也就是Lambda表达式是用在函数式接口中的,一条Lambda表达式就相当于一个接口的实例。即3的Lambda表达式就相当于4中的匿名内部类。

	1:
	@FunctionalInterface
    public interface FruitPredicate<T,R> {
    R test(T t);
    }
	
	2:
	public static List<Fruit> filter(List<Fruit> inventory,FruitPredicate<Fruit,Boolean> fp){
        List<Fruit> result = new ArrayList<>();
        for (Fruit f : inventory){
            if(fp.test(f)){
                result.add(f);
            }
        }
        return result;
    }
	
	3:
	filter(fruitList,a ->"green".equals(a.getColor()));
	
	4:
	filter(fruitList, new FruitPredicate<Fruit, Boolean>() {
            @Override
            public Boolean test(Fruit fruit) {
                return "green".equals(fruit.getColor());
            }
        });

       那么是不是我们要使用Lambda表达式都需要事先定义一个函数式接口呢?java设计师在java.lang.function包中给我们提供了一些定义好的函数式接口。如Predicate<T>、Function<T, R>、Supplier<T>、Consumer<T>等等。
       函数式接口与Lambda表达式的结合中需要匹配。如果函数式接口的抽象方法的签名与Labmda表达式的签名一样,就是匹配的就拿函数式接口1来说签名是(T,R)->R,3中的Lambda表达式的签名是(Fruit,Boolean) -> Boolean;因此是匹配的;我们举一个签名不匹配的例子。

5:
	@FunctionalInterface
	public interface Predicate<T> {
		boolean test(T t);
	}

    函数式接口5的签名是T->boolean;因此这样的Lambda表达式是正确的:Predicate<Fruit> predicate = f -> "green".equals(f.getColor());因为签名是Fruit -> boolean;如果Lambda表达式是f->f.getColor();,就是错误的,因为签名为Fruit -> int;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值