1. 场景例子
    假设现在是一个万人选对象的现场。活动方的后台屯了一堆资源,男男女女老老少少都有,上台的嘉宾可以说出自己的要求,然后台上出现符合你要求的人,介绍下自己。万人选妃,吃鸡。
    人类定义:

    package jdk8.lambada.case1;
    
    import java.time.LocalDate;
    
    public class Person {
        /**
         * 姓名,我们是实名制的相亲活动,必须是真实姓名
         */
        String name;
        /**
         * 出生年月,年龄很重要啊
         */
        LocalDate birthday;
        /**
         * 这也很重要啊
         */
        Sex gender;
        /**
         * 描述下呗
         */
        String describe;
    
        public String getDescribe() {
            return describe;
        }
    
        public void setDescribe(String describe) {
            this.describe = describe;
        }
    
        public int getAge() {
            return LocalDate.now().compareTo(birthday);
        }
    
        public void printPerson() {
        }
        public enum Sex {
            MALE, FEMALE
    
        }
    
        public Person(String name, LocalDate birthday, Sex gender, String describe) {
            this.name = name;
            this.birthday = birthday;
            this.gender = gender;
            this.describe = describe;
        }
    
        public Person() {
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public LocalDate getBirthday() {
            return birthday;
        }
    
        public void setBirthday(LocalDate birthday) {
            this.birthday = birthday;
        }
    
        public Sex getGender() {
            return gender;
        }
    
        public void setGender(Sex gender) {
            this.gender = gender;
        }
    
        public static int compareByAge(Person a, Person b) {
            return a.birthday.compareTo(b.birthday);
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", birthday=" + birthday +
                    ", gender=" + gender +
                    ", describe='" + describe + '\'' +
                    '}';
        }
    }
    

    我们的资源是充分的,少资源就new一个。

      public static List<Person> createSource(){
        //我们先初始化后台资源,程序员缺啥new啥
        List<Person> list = new ArrayList<>();
        //先来一群女的
        list.add(new Person("韩梅梅", LocalDate.of(1990, 1, 2), Person.Sex.FEMALE, "人美成绩好,英语专家"));
        list.add(new Person("lucy", LocalDate.of(1994, 8, 20), Person.Sex.FEMALE,  "来自英国,lily的姐妹"));
        list.add(new Person("翠花", LocalDate.of(1980, 1, 7), Person.Sex.FEMALE, "做的酸菜很好吃"));
        list.add(new Person("李倩倩", LocalDate.of(1992, 8, 2), Person.Sex.FEMALE,"护士妹妹"));
        list.add(new Person("慕容玉", LocalDate.of(1988, 1, 7), Person.Sex.FEMALE,  "御姐气质"));
        list.add(new Person("李倩倩", LocalDate.of(1992, 8, 2), Person.Sex.FEMALE,  "家里很有钱"));
        list.add(new Person("罗玉凤", LocalDate.of(1985, 1, 2), Person.Sex.FEMALE,  "我只要冠希哥"));
        list.add(new Person("李小璐", LocalDate.of(1985, 1, 2), Person.Sex.FEMALE, "喜欢做头发"));
        //再来一群男的
        list.add(new Person("陈冠希", LocalDate.of(1980, 1, 2), Person.Sex.MALE,  "机不离身"));
        list.add(new Person("慕容复", LocalDate.of(1960, 10, 2), Person.Sex.MALE, "富N代"));
        list.add(new Person("张三", LocalDate.of(1990, 1, 2), Person.Sex.MALE,  "无名小卒"));
        list.add(new Person("李四", LocalDate.of(1980, 1, 2), Person.Sex.MALE,  "张三同村村长家的"));
        list.add(new Person("史泰龙", LocalDate.of(1960, 1, 2), Person.Sex.MALE,  "很能打"));
        return list;
    }
    

    一号嘉宾:
    大龄未婚男,急着结婚,要求简单,只要是女女就行。很简单的愿望,实现也很简单。
    实现:

    /**
     * 选个简单对象就好,没啥要求
     * @param personList
     */
    public static void chooseSimpleObject(List<Person> personList){
        for (Person person : personList) {
            if (person.getGender() == Person.Sex.FEMALE) {
                System.out.println(person);
            }
        }
    }
    // main 函数
    public static void main(String[] args) {
        List<Person> personList = createSource();
        chooseSimpleObject(personList);
    }
    /** 输出:
    Person{name='韩梅梅', birthday=1990-01-02, gender=FEMALE, describe='人美成绩好,英语专家'}
    Person{name='lucy', birthday=1994-08-20, gender=FEMALE, describe='来自英国,lily的姐妹'}
    Person{name='翠花', birthday=1980-01-07, gender=FEMALE, describe='做的酸菜很好吃'}
    Person{name='李倩倩', birthday=1992-08-02, gender=FEMALE, describe='护士妹妹'}
    Person{name='慕容玉', birthday=1988-01-07, gender=FEMALE, describe='御姐气质'}
    Person{name='李倩倩', birthday=1992-08-02, gender=FEMALE, describe='家里很有钱'}
    Person{name='罗玉凤', birthday=1985-01-02, gender=FEMALE, describe='我只要冠希哥'}
    Person{name='李小璐', birthday=1985-01-02, gender=FEMALE, describe='喜欢做头发'}
    */
    

    我们写了一个chooseSimpleObject方法,方法很简单。一号嘉宾的要求得到满足,但是可以没有牵手成功,很遗憾。
    二号嘉宾:
    老子有钱,要找就找个年轻的,年龄在18-25。这个要求,也容易满足。各位嫖客,呸呸呸,各位看官请看:

      /**
       * 选择个漂亮的
       * @param personList
       */
      public static void chooseYongObject(List<Person> personList) {
          for (Person person : personList) {
              if (person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18) {
                  System.out.println(person);
              }
          }
      }
      //main函数
      public static void main(String[] args) {
          List<Person> personList = createSource();
          chooseYongObject(personList);
      }
      /**输出:
        Person{name='lucy', birthday=1994-08-20, gender=FEMALE, describe='来自英国,lily的姐妹'}
      */
    

    三号嘉宾:
    凤姐上来了,我只要冠希哥。这个。。。。好吧,给你冠希哥。接好了。

        /**
         * 只要陈冠希
         * @param personList
         */
        public static void chooseChenguanxi(List<Person> personList) {
            for (Person person : personList) {
                if ("陈冠希".equals(person.getName())) {
                    System.out.println(person);
                }
            }
        }
        //main 函数
        public static void main(String[] args) {
            List<Person> personList = createSource();
            chooseChenguanxi(personList);
        }
        /**输出:
        Person{name='陈冠希', birthday=1980-01-02, gender=MALE, describe='机不离身'}
        */
    

    从上面三个例子中,我们发现,每个人的择偶标准都不一样,但是流程都是一样的,都是for-if-then结构,换句话说,if的条件是变的。那么这个变动的部分能不能封装起来,以变量的形式传入目标方法呢?答案是当然行的。我们定义一个公共的择偶方法chooseObjectByCondition(),如下:

      /**
         * 择偶方法
         * @param personList
         * @param chooseCondition
         */
        public static void chooseObjectByCondition(List<Person> personList, ChooseCondition chooseCondition) {
            for (Person person : personList) {
                if (chooseCondition.isRightObject(person)) {
                    System.out.println(person);
                }
            }
        }
    

    接口ChooseCondition

    package jdk8.lambada.case1;
    public interface ChooseCondition {
        /**
         * 是那个人吗?
         * @param person
         * @return
         */
        boolean isRightObject(Person person);
    }
    

    接口ChooseCondition的实现,满足第二个嘉宾的条件实现。

    class ChooseYong implements ChooseCondition{
      @Override
      public boolean isRightObject(Person person) {
          return person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18;
      }
    }
    

    在main方法调用

        public static void main(String[] args) {
            List<Person> personList = createSource();
            chooseObjectByCondition(personList, new ChooseYong());
        }
    

    我们用了一个接口,把if条件抽象成一个方法,在目标方法接受接口的形参,调用的时候根据不同人的择偶标准实例化不同的接口实现类。显然,这种方法还是有瑕疵的,注意这里有个ChooseCondition的实现,如果人越多,像这种实现类就会越来越多,项目就会越来越臃肿。所以,下一步,去掉接口实现类,用匿名内部类(Anonymous class)优化下。

    public static void main(String[] args) {
         List<Person> personList = createSource();
         chooseObjectByCondition(personList, new ChooseCondition() {
             @Override
             public boolean isRightObject(Person person) {
                 return person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18;
             }
         });
     }
    

    嗯,代码减少了很多。还能不能再把接口干掉呢?额,如果是JDK8以下的话,是不行的,但是JDK8给我们预置了很多接口函数。接口函数,我们待会介绍。先把上面的自定义接口干掉。
    修改main()方法入参为JDK8预置判断接口Predicate

        /**
         * 择偶方法
         * @param personList
         * @param predicate
         */
        public static void chooseObjectByCondition(List<Person> personList, Predicate predicate) {
            for (Person person : personList) {
                if (predicate.test(person)) {
                    System.out.println(person);
                }
            }
        }
    

    main()函数做对应修改

      public static void main(String[] args) {
          List<Person> personList = createSource();
          chooseObjectByCondition(personList, new Predicate<Person>() {
              @Override
              public boolean test(Person person) {
                  return person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18;
              }
          });
      }
    

    又精简了一步,好哈皮。其实,这离我们今天要说得lambada表达式只有一步之遥了,下面我们就跨出这一步,走起,对main函数再改造下。

    public static void main(String[] args) {
           List<Person> personList = createSource();
           chooseObjectByCondition(personList, person -> person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18);
       }
    

    到此为止,lambada表达式闪亮登场,我们再把上面的业务完善下,完全用jdk8的特性替换。

      /**
       *  择偶,符合条件的再干些事情
       * @param personList
       * @param predicate
       * @param function
       * @param consumer
       */
        public static void chooseObjectByConditionDoSomeThing(List<Person> personList, Predicate<Person> predicate,
                                                   Function<Person, String> function, Consumer<String> consumer) {
            for (Person person : personList) {
                if (predicate.test(person)) {
                    String s = function.apply(person);
                    consumer.accept(s);
                }
            }
        }
    
    
    public static void main(String[] args) {
            List<Person> personList = createSource();
            chooseObjectByConditionDoSomeThing(personList, person -> {
                return person.getGender() == Person.Sex.FEMALE && person.getAge() <= 25 && person.getAge() >= 18;
            }, Person::getName, System.out::println);
        }
    

    再上个终极版本

      public static void main(String[] args) {
           List<Person> personList = createSource();
           personList.stream().filter(person -> person.getGender() == Sex.FEMALE && person.getAge() <= 25 &&
                   person.getAge() >= 18).map(Person::getName).forEach(System.out::println);
       }
    
  2. 什么是Lambda表达式?
    Lambda表达式可以封装单个行为单元,然后传给其他代码。
    语法:

     p -> p.getGender() == Person.Sex.MALE
         && p.getAge() >= 18
         && p.getAge() <= 25
    

    分为三部分:

    • 入参,p是省略后的格式,完整的格式为(Person p),入参的类型可以省略。只有一个入参时,小括号也可以省略。当有多个入参时,以逗号隔开,如(p1,p2);
    • ->,箭头;
    • 函数体,表达式的处理逻辑。多行代码时需要加上大括号,只有一行代码时大括号可以省略,表达式有返回值时,return关键字是可选。
posted on 2018-09-13 16:22  落叶伯爵  阅读(116)  评论(0编辑  收藏  举报