继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Java函数式编程(1):Lambda表达式(1)

湘王爱娟娟
关注TA
已关注
手记 101
粉丝 7
获赞 15

您好,我是湘王,这是我的慕课手记,欢迎您来,欢迎您再来~


Java在其技术发展周期中经历过几次比较重要的变化如果不是这几次比较重要的变化恐怕不会有现在这样的江湖地位个人看来至少有两次一是2010~2011年兴起的移动应用开发Android的出现Java狠狠地出了次风头再就是2014年发布的Java8,这个版本也是Java8之前和后续所有版本的一个分水岭尽管在Java8之后出现了更多的版本也加入了很多的功能但从改变上来上Java8可以说是一次脱胎换骨的变化而原因就在于它引入了函数式编程这个没有绝对的正确与否仅是个人之间)。

Java码农都知道虽然都学过集合I/O多线程泛型抽象类注解反射等若干高大上的内容但实际上真正在工作中最头疼用得最多的却是集合操作这也很好理解业务数据就是业务的血肉而对数据的读取存储传输等操作会业务规则变得非常麻烦

比如像单纯数字列表的筛选、排序、去重,对于JDK7及以下版本来说会比较麻烦,类似[1, 3, 7, 2, 10, 13, 11, 9, 22]这样的列表,即使是比较简单的冒泡排序,也至少需要一个嵌套循环

再就是含有复杂嵌套对象的列表,其查询、排序、筛选等需求,如果使用目前的Java集合类库,实现起来会异常麻烦,例如,假如现在需要实现让不同公司的员工举行联谊,将信息登记在一个列表上,然后选出未婚员工,解决员工单身问题且将全部的员工按年龄从小到大排序,如果要你来实现,该怎么做?这其实就是一个列表数据筛选的问题,List<Company<Employee>>这样的集合数据进行排序、汇总等操作,会非常麻烦

也就是假如有下面的类和对象

public class Company<T> {
   public enum Type { BIG, SMALL };
   private String name;
   private Type type;
   private List<T> employees;

   public Company(final String name, final Type type, final List<T> employees) {
      super();
      this.name = name;
      this.type = type;
      this.employees = employees;
   }

   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public Type getType() {
      return type;
   }
   public void setType(Type type) {
      this.type = type;
   }
   public List<T> getEmployees() {
      return employees;
   }
   public void setEmployees(List<T> employees) {
      this.employees = employees;
   }
   @Override
   public String toString() {
      return this.name;
   }
}



public class Employee {
   public enum Type { MANAGER, SELLER, OFFICER };
   private String name;
   private String genger;
   private Integer age;
   private boolean married;
   private Type type;
   public Employee(final String name, final String genger, final Integer age, final boolean married, final Type type) {
      super();
      this.name = name;
      this.genger = genger;
      this.age = age;
      this.married = married;
      this.type = type;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getGenger() {
      return genger;
   }
   public void setGenger(String genger) {
      this.genger = genger;
   }
   public Integer getAge() {
      return age;
   }
   public void setAge(Integer age) {
      this.age = age;
   }
   public boolean isMarried() {
      return married;
   }
   public void setMarried(boolean married) {
      this.married = married;
   }
   public Type getType() {
      return type;
   }
   public void setType(Type type) {
      this.type = type;
   }
   @Override
   public String toString() {
      return this.name + "(" + this.genger + ")-" + this.age;
   }
}



public static void main(String[] args) {
   // 创造数据
   List<Company<Employee>> list = new ArrayList<>();
   List<Employee> employees = Arrays.asList(
      new Employee("张勇", "男", 28, true, Employee.Type.MANAGER),
      new Employee("李强", "男", 22, false, Employee.Type.SELLER),
      new Employee("王武", "男", 32, false, Employee.Type.SELLER),
      new Employee("梅丽", "女", 26, true, Employee.Type.OFFICER),
      new Employee("郑帅", "男", 29, false, Employee.Type.OFFICER),
      new Employee("曾美", "女", 27, true, Employee.Type.SELLER),
      new Employee("郝俊", "男", 22, true, Employee.Type.SELLER),
      new Employee("方圆", "女", 24, false, Employee.Type.SELLER)
   );
   Company<Employee> moubao = new Company<Employee>("某宝", Company.Type.BIG, employees);

   employees = Arrays.asList(
      new Employee("吴琼", "女", 27, true, Employee.Type.SELLER),
      new Employee("陈辰", "女", 20, false, Employee.Type.OFFICER),
      new Employee("刘能", "男", 25, true, Employee.Type.OFFICER),
      new Employee("周七", "男", 29, false, Employee.Type.OFFICER),
      new Employee("汪旺", "男", 21, false, Employee.Type.OFFICER),
      new Employee("胡涂", "男", 27, false, Employee.Type.OFFICER),
      new Employee("杨茂", "男", 34, true, Employee.Type.MANAGER),
      new Employee("朱坚", "男", 30, false, Employee.Type.MANAGER)
   );
   Company<Employee> mouxin = new Company<Employee>("某东", Company.Type.BIG, employees);

   employees = Arrays.asList(
      new Employee("冯过", "男", 35, false, Employee.Type.SELLER),
      new Employee("何花", "女", 27, false, Employee.Type.MANAGER),
      new Employee("卫精", "男", 25, true, Employee.Type.OFFICER),
      new Employee("施工", "男", 28, false, Employee.Type.OFFICER),
      new Employee("沈月", "女", 24, false, Employee.Type.OFFICER),
      new Employee("乐欢", "女", 22, false, Employee.Type.OFFICER),
      new Employee("安全", "男", 33, true, Employee.Type.MANAGER),
      new Employee("林森", "男", 26, true, Employee.Type.SELLER)
   );
   Company<Employee> wahaha = new Company<Employee>("某哈哈", Company.Type.SMALL, employees);
   // 加入列表
   list.add(moubao);
   list.add(mouxin);
   list.add(wahaha);
}

  

 

那么当要实现某宝某东和某哈哈的员工联谊并解决单身问题时就会比较麻烦就像这样

/**
 * 方式一:公司联谊未婚员工登记表:传统方法
 */
List<Employee> unMarriedList1 = new ArrayList<>();
for (Company<Employee> company : list) {
   if (company.getType() == Company.Type.BIG) {
      List<Employee> emps = company.getEmployees();
      // 如果不用Lambda,则必须再次调用排序算法
      for (Employee tempEmployee : emps) {
         if (!tempEmployee.isMarried()) {
            unMarriedList1.add(tempEmployee);
         }
      }
   }
}
// 不用Lambda做排序会非常麻烦
System.out.println("unMarriedList1 -> " + unMarriedList1);

 

这种方式就完全是一种面向过程的编程号称纯面向对象设计编程的Java在解决这种问题时就是一个讽刺

 

既然有了问题肯定要正视并解决但解决的方法不在于怎么改进这种代码大师们的思路往往清奇但管用)。

Java还在使用Swing做一些小组件的时候Swing虽然已经完全被主流应用淘汰了但代码还保留在Java中),大师们就注意到了一个现象

http://img.mukewang.com/636281b900018e3b06460600.jpg

 

可以看到红色部分的代码几乎没有差别除了一点内容之外代码几乎99%都是一样的而且类似于


http://img1.mukewang.com/636281c40001cf1204530125.jpg


这种代码块Java中随处可见而这种代码块本质上是由actionListener变量保存所以,这一过程类似于「将代码赋值给变量」。

再于是,「优化过程开始了


http://img2.mukewang.com/636281ce000182c708930191.jpg

 

1、因为ActionListener是以匿名类的方式实现的,既然它都已经不想让人知道自己干了什么,退出江湖了,又何必再露脸呢

2、因为button的addActionListener里面已经要求了ActionListener作为参数,所以其实只要是个稍微聪明点的编译器,它自己就应该能够推断出来需要什么,不用我再来告诉它一次,有点多此一举了

3、第三点就是,其实咱们写代码,最终是只需要两个东西的,也就是数据和结果,而且这个类本身也是匿名的,所以它完全可以去掉,去掉以后应该是这样的


http://img4.mukewang.com/636281d7000136bd08930146.jpg

 


接下来public是多余的,因为只是作为参数了,有没有public没啥区别,所以去掉;然后void也是多余的,编译器可以推断出来有没有返回值,以及它的返回值是啥;然后方法名actionPerformed也是多余的,因为这段代码已经被赋值给「代码块」了,所以它不需要,也不配拥有自己的名字了,所以结果应该是这样的


http://img2.mukewang.com/636281e00001e6ef08930146.jpg

 

精简成这样了而且进行到这一步,我想Java8开发组的工程师们已经知道自己在干嘛了。刚开始只是尝试着找到优化的方向,另外说一句,咱们可能用了不到几分钟就做到了这一步,那些工程师们可是呕心沥血了几年才达到了这一步的,所以在这里,我们需要向那些优秀的工程师们致敬,感谢他们为我们这些程序员所做出的付出,为整个Java开发社区和生态所做出的贡献然后,和返回类型一样,需要什么类型的数据编译器也应该是能够自己推断出来的,所以括号里那个ActionEvent也可以省略了


http://img2.mukewang.com/636281e60001c69f08930146.jpg

 

而进行到这一步,其实代码已经可以放在一行了,就像这样


http://img3.mukewang.com/636281ed00017b5109200146.jpg

 

但这样太丑了我想应该是有些颜值控的工程师最终做了这样的改动


http://img.mukewang.com/636281f500016c7b09100146.jpg

 

终于大功告成所以可以用一张图来回顾一下整个Lambda的诞生过程


http://img3.mukewang.com/636281fd00018bb806320361.jpg

 

虽然这只是我们现在看到的一小步但是负责维护Java的工程师们应该是往前走了一大步这种死磕的精神才是每个码农工程师们应该学习的


 

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~



打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP