java8新特性之lambda:lambda的结构和使用

lambda的结构和使用

上回说到lambda之行为参数化了,里面也有使用lambda的一个小栗子,让我们见识到了lambda使代码变得是多么的美丽易读。今天,小隐就来整理一下lambda的结构和使用方式。

lambda的结构

lambda的结构有两种:
(parameters) -> expression
(parameters) -> { statements; }

parameters:参数,多个以逗号隔开。
expression :语句,即一句话或者一个操作。
statements :陈述,一个或多个语句。

这种语法在C#和Scala等语言中的类似功能广受欢迎。情况就不多做介绍了,注意花括号即可。不过作为一个刚换驾坐的人来说,更加推荐第二种方式,当然当你的代码足够简单明了的时候,第一种也确实更加赏心悦目一点。

知道了结构,那么能在哪里用呢?lambda只能在函数式接口中使用。

lambda的使用条件

lambda只能在函数式接口中使用,而函数式接口概括起来就是只有一个抽象方法的接口。这里为什么要强调抽象,因为现在java的接口中,方法不仅仅只有抽象方法了。因为某些原因就目前java的发展来看,接口越发的被安排去代替抽象类了。更从侧面展示了多重继承的影子(其实java早就想这么干了)。
在上一篇的行为参数化文中,我们帮红姐找手机时使用到了lambda,当时说看似传递的是行为,其实传递的是对象。原因就是传递的是函数式接口。而lambda只有在接收函数式接口的地方才可使用。以此来解决一个疑惑,这里的代码写了一个lambda那么这个lambda是代替什么的呢?代替的就是方法参数中的函数式接口。通过java的类型推断机制也就能确定这里的lambda是代替的哪个函数式接口了。
其实就我目前的认知来说,在自己的项目中定义函数式接口的地方极其少,甚至说都没有,这也是我后续需要探索的地方。当我发现某些情况使用自定义的函数式接口是非常不错的解决办法的时候,我也会回来补充到这里。目前作为整理的内容其实在我项目中是并未使用的,仅做为学习。
这里还是加上一个代码例子吧要不然感觉整理的内容有些空洞晦涩难懂。
依旧是上一篇中提到的帮美女红姐筛选手机的方法。我们定义一个函数式接口,然后在一个方法中把函数式接口作为参数,最后在调用这个方法的时候用lambda作为函数式接口的实现类去使用。下列内容是在同一个java类中的代码。

/**
* 定义要使用的类,这里为了方便使用嵌套类
*/
   private static class Phone {
       private String brand;
       private Integer price;
       private Boolean canUse;
       public String getBrand() { return brand; }
       public void setBrand(String brand) { this.brand = brand; }
       public Integer getPrice() { return price; }
       public void setPrice(Integer price) { this.price = price; }
       public Boolean getCanUse() { return canUse;}
       public void setCanUse(Boolean canUse) { this.canUse = canUse; }
   }
/**
* 定义函数式接口,这里的注解是1.8新加的,用来显式的声明这是一个函数式接口,同时编译器会对这个函数式接口进行检查,当不符合函数式接口的标准时不能编译通过。但是没有加此注解的接口如果满足函数式接口的定义依旧会被当做函数式接口。
*/
@FunctionalInterface
private interface Predicate<T>{
       Boolean test(T t);
   }
/**
* 定义把函数式接口作为参数的方法
*/
public static <T> List<T> screenPhone(List<T> list,Predicate<T> predicate) throws Exception{
       if( list==null || list.size()==0 || predicate == null){
           throw new Exception("参数不全");
       }
       List<T> resultList = new ArrayList<>();
       for (T item:list) {
           if(predicate.test(item)){
               resultList.add(item);
           }
       }
       return resultList;
   }
/**
* 在test1测试方法中调用方法
*/
public void test1() throws Exception{
       //参数
       List<Phone> list = new ArrayList<>();
       //返回值
       List<Phone> phones = new ArrayList<>();
       //筛选价格小于一千的苹果手机
       phones = screenPhone(list,phone -> {return "apple".equals(phone.getBrand())&&1000>phone.getPrice();});
   }

有时候lambda表达式只是调用了一个已经声明过的方法,为了增加可读性和进一步简化,可以使用方法引用。方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。
方法引用可以被看作仅仅调用特定方法的Lambda的一种快捷
写法。它的基本思想是,如果一个Lambda代表的只是“直接调用这个方法”,那最好还是用名称
来调用它,而不是去描述如何调用它。

/**
* 筛选可用的手机
*/
public void test1() throws Exception{
        //参数
        List<Phone> list = new ArrayList<>();
        //返回值
        List<Phone> phones = new ArrayList<>();
        //使用方法引用
        phones = screenPhone(list,Phone::getCanUse);
        //使用lambda
        //phones = screenPhone(list,phone->phone.getCanUse());
    }

小隐小故事——函数式接口

近来南下诸国越来越躁动不安,作为对东南军区司令员的小隐目前正在召集部下开会。北方下发命令,要开始提防南下诸国的动作,安排好应对方针,做好必要时刻采取使用武力的准备。“你们觉得应该如何?”小隐环视一周。“小小水贼,司令且看我三日平了这盆国!”赛甘宁说到。隐司令看向了智囊团。赛孔明眉头紧锁,说:“这南下这盆国和我们隔海相望,这个事情理应让赛甘宁去,不过怕这些贼人龟缩内陆,赛甘宁的水军是在水上作战厉害,不过这上了陆地作战,赛武圣应该处理起来更得心应手啊。”
“不论你们水上还是陆地,我斯奈克的支援永远不会少了的!”空军大将斯奈克也说出了自己的想法。赛孔明突然明目一闪。“我们陆地作战有赛武圣,水上作战有赛甘宁,我们空中作战有斯奈克。不过有一些战斗情况瞬息万变需要能有一支部队应对这种变化的战斗情况,适应海陆空三种作战形态,方可处理这等棘手的问题啊!”“恩”隐司令点头道:“现在我正式成立函数式接口军,下设特种作战中队战狼中队,进行全方位训练,应对各种战场突发情况,随时提供能解决特殊战况问题的部队!”环视一周后,目标定格在一个人头上。“我现在正式任命拉姆达为东南军区函数式接口军特种作战中队战狼中队队长,代号冷锋!”
java8新特性之lambda:lambda的结构和使用_第1张图片
哈哈,真特么能吹!骚话说到这。我希望lambda也能成为个位看官编程武器中的特种武器来使用。而函数式接口就是指定义了一个抽象方法的接口,用来应对各种突发战况。当你调用的时候只需要通过lambda传递不同的作战计划即可。同时国家(java的类库)中很多地方也定义了很多方法来使用你的特种部队(函数式接口)尤其是新加的集合类库中使用居多。小隐也会在接下来整理java8中关于stream的知识和lambda与stream的结合使用。

你可能感兴趣的:(lambda,lambda使用情形,java8)