本文分两部分:

  1. 语法简单说明
  2. lambda的使用

注:这两部分内容均以类+注释的方式进行说明,并且内容均来自官方教程(https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)。

第一部分:

/**
* 语法说明类
*
* lambda表达式包含下面几个要素:
* 1、逗号分隔的参数列表,如CheckPerson。test(Person p),其中p表示一个Person的对象实例
* 2、向右箭头 →, 箭头左侧是表达式入参,箭头右侧是表达式本身
* 3、表达式体,包含单个表达式或者一个语句块
*
* @author zhuotao
*
*/
public class SyntaxInstruction {

  public static void main(String[] args) {

List<Person> persons = PersonGenerator.generatePerons();
  printPerson(persons, p -> p.getAge() > 30 && p.getAge() < 50);
}

public static void printPerson(List<Person> persons, CheckPerson cp) {
  for(Person p : persons) {
    if(cp.test(p)) System.out.println(p);
  }
}
}

interface CheckPerson{
  public boolean test(Person p);
}

第二部分:

假设一种场景:
A正在开发一个社交网络应用,考虑添加一个功能——管理员可以根据用户(Person)的不同特征,执行不同的操作,比如发送信息。

approaches是A写的不同的实现,从a1 ~ a8,看看每个方法较之前有什么明显的提升。

备注:1> Person 社交网络应用用户类  2> PersonGenerator 用户列表模拟产生类

方法一:

/**
* 方法一:创建一个方法,用于查询某个特征的用户
* 1、方法入参:
* persons 用户列表
* age 约束条件,最低年龄
* 2、输出打印满足条件的用户信息
*
* 不过,总感觉有什么不对,如果有一天功能的约束条件增加该怎么办?比如,“同事满足age<50”的条件
* 所以,写了第二个方法,见a2.Approch2
*
* @author zhuotao
*
*/
public class Approch1 {

  public static void main(String[] args) {
    List<Person> persons = PersonGenerator.generatePerons();
    printPersonOlderThan(persons, 30);
  }

  public static void printPersonOlderThan(List<Person> persons, int age) {
     for(Person p : persons) {
      if(p.getAge() > age) {
        p.printPerson();
      }
     }
  }

}

方法二:

/**
* 方法二:增强方法的限定规则,判断年龄时,用区间进行判断
* 额,这跟第一种方法就是换汤不换药嘛,没什么改进哈~Σ( ° △ °|||)︴
*
* 于是,第三种方案应运而生。见 a3/Approach3
*
* @author zhuotao
*
*/
public class Approach2 {

public static void main(String[] args) {
  List<Person> persons = PersonGenerator.generatePerons();
  printPersonOlderThan(persons, 30, 50);
}

public static void printPersonOlderThan(List<Person> persons, int low, int high) {
  for(Person p : persons) {
    if(p.getAge() > low && p.getAge() < high) {
      p.printPerson();
    }
  }
}

}

方法三:

/**
* 方法三:创建规则判断接口
* 将规则判断独立出业务判断,如果新增规则约束,那么只需要实现CheckPerson,重写test即可
*
* 仔细想,要是规则很多,肿么办?肿么办?
* 先后有100种规则,是不是要创建100种实现?那类的数量。。。~~~~(>_<)~~~~ 此路不通~
*
* 于是,试试第四中方法,见 a4/Approach4
*
* @author zhuotao
*
*/
public class Approach3 {

public static void main(String[] args) {

  List<Person> persons = PersonGenerator.generatePerons();
  printPerson(persons, new SearchPersonsByAage());

}

public static void printPerson(List<Person> persons, CheckPerson check) {
  for(Person p : persons) {
    if(check.test(p)) p.printPerson();
  }
}

}

class SearchPersonsByAage implements CheckPerson {

@Override
public boolean test(Person p) {
  return p.getAge() > 30 && p.getAge() < 50;
}

}

interface CheckPerson {
  public boolean test(Person p);
}

方法四:

/**
* 方法四:使用匿名内部类
* 使用这种方法,再也不用担心规则类的膨胀问题了~哇咔咔~
*
* 可是,这真的就是想要的方案么?蛋然不是啦~~
*
* 来吧,进入今天的主题——lambda expressions, 见a5/Approach5
*
* @author zhuotao
*
*/
public class Approach4 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    printPerson(persons, new CheckPerson() {
      @Override
      public boolean test(Person p) {
        return p.getAge() > 30 && p.getAge() < 50;
      }
    });

  }

  public static void printPerson(List<Person> persons, CheckPerson check) {
    for(Person p : persons) {
      if(check.test(p)) p.printPerson();
    }
  }

}

interface CheckPerson {
  public boolean test(Person p);
}

方法五:

/**
* 方法五,使用lambda表达式
* lambda表达式,需要依赖一个功能接口。这里的功能接口,是指只包含一个抽象方法的接口。如,下面的CheckPerson
*
* 这个例子,发生了什么,连匿名内部类都不需要了,(~ o ~)~zZ 也太简洁了吧~
* 同样是规则判断,这里只需要一个功能接口,一个表达式就解决了规则判断的问题。 (*^__^*)
*
* 这就满足了? 还没有结束哦,卡木昂,北鼻 ,随我来,见 a6/Approach6
*
* @author zhuotao
*
*/
public class Approach5 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    printPerson(persons, (Person p) -> p.getAge() > 30 && p.getAge() < 50);
    // 等价于
    //printPerson(persons, p -> p.getAge() > 30 && p.getAge() < 50);

  }

  public static void printPerson(List<Person> persons, CheckPerson check) {
    for(Person p : persons) {
      if(check.test(p)) p.printPerson();
    }
  }

}

interface CheckPerson {
  public boolean test(Person p);
}

方法六:

/**
* 方法六:使用通用功能接口+lambda表达式
* 知道方法5的问题在哪里么? 我来告诉你哈~~
* 因~为~那~个~功~能~接~口~不~通~用~,如果我判断Person之外的对象,岂不是~
*
* 是的,将功能进行通用化处理,参考 Predicate<T> T通用的泛型
*
* 该逻辑: printAdmin(amdins, admin -> "xxxxxx".equals(admin.getPrivilegeCode()));
*
* 在这里lambda的优势已经基本上明了——
* 使用功能接口,替换内部类的使用,降低类膨胀风险;
* 表达式语法简单,简洁易懂;
* 减少coding
*
* 以上,只是自己的片面之言,总结未必到位欢迎补充。
*
* 看到这,lambda已经基本结束了,不过,如果继续看下面的优化相信你会有更大的收获,见 a7/Approach7
*
* @author zhuotao
*
*/
public class Approach6 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    printPerson(persons, (Person p) -> p.getAge() > 30 && p.getAge() < 50);
    // 等价于
    //printPerson(persons, p -> p.getAge() > 30 && p.getAge() < 50);

    // 下面只是一个示例,用于说明通用功能接口的优势
    // List<Aministrator> amdins = new ArrayList<Aministrator>();
    // printAdmin(amdins, admin -> "xxxxxx".equals(admin.getPrivilegeCode()));

  }

  public static void printPerson(List<Person> persons, Predicate<Person> check) {
    for(Person p : persons) {
      if(check.test(p)) p.printPerson();
    }
  }

  public static void printAdmin(List<Aministrator> admins, Predicate<Aministrator> check) {
    for(Aministrator admin : admins) {
      if(check.test(admin)) admin.printAdmin();
    }
  }

}

class Aministrator {


private String name;
private String id;
private String privilegeCode;
public String getName() {
  return name;
}
public void setName(String name) {
  this.name = name;
}
public String getId() {
  eturn id;
}
public void setId(String id) {
  this.id = id;
}
public String getPrivilegeCode() {
  return privilegeCode;
}
public void setPrivilegeCode(String privilegeCode) {
  this.privilegeCode = privilegeCode;
}

@Override
public String toString() {
  return "Aministrator [name=" + name + ", id=" + id + ", privilegeCode="
    + privilegeCode + "]";
}

public void printAdmin() {
  System.out.println(toString());
}

}

interface Predicate<T> {
  public boolean test(T t);
}

方法七:

/**
* 方法七:怎么将lambda表达式贯穿到整个应用呢?
* 我稀饭这个标题,因为,这表达的是一种技巧,一种思路
*
* 试想,printPerson方法做了什么?1、接收用户列表 2、规则判断 3、输出打印符合条件的用户信息
* 那如果我有相似的逻辑:比如 1、接收用户列表(待处理数据) 2、执行某个规则(lambda表达式) 3、发送用户信息(操作) 该如何操作呢?
* 这里还是以List<Person> 作为待处理数据,进行优化
* 看processPersons(persons, p -> p.getAge() > 30 && p.getAge() < 50, p -> p.printPerson()); 这个逻辑,你会发现;
* 相同的数据,将规则和规则之后的操作进行了分离。
*
* 那啥,是不是很带感,那就继续,见 a8/Approach8
*
* 注意: 这里使用了 java.util.function.Consumer, 没看错,在jdk8中新引入的function包
*
* 不妨看看Consumer的注释信息(除了accept方法,还有个默认方法,感兴趣的同学可以研究下~)
*
* **
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*
* @FunctionalInterface //这里使用了功能接口的标注
public interface Consumer<T> {......}
*
*
* @author zhuotao
*
*/
public class Approach7 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    processPersons(persons, p -> p.getAge() > 30 && p.getAge() < 50, p -> p.printPerson());

  }

  public static void processPersons(List<Person> persons, Predicate<Person> check, Consumer<Person> block) {
    for(Person p : persons) {
      if(check.test(p)) block.accept(p);;
    }
  }

}

interface Predicate<T> {
  public boolean test(T t);
}

方法八:

/**
* 方法八:依然是将lambda表达式运用到整个应用
* 整个题目的调调跟方法七很像,其实a8和a7的关系就像是a6和a5的关系,只是用来说明通用性的
*
* 看到下面的逻辑,有什么想说的? 我是想说,简直太神奇了~~喵喵的~~神奇的jdk8~哇咔咔~
*
* 不过,在新事物(Consumer 和 Function)面前是不是感觉有点不适应,那么接下来就再次见证奇迹吧~
* 见~~~~a9/Approach9
*
* 值得注意的是,这里同样使用了jdk8新增的一个类:java.util.function.Function
* 该类注释如下:
* **
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*
* @author zhuotao
*
*/
public class Approach8 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    processElements(
          persons,
          p -> p.getAge() > 30 && p.getAge() < 50,
          p -> p.getName(),
          name -> System.out.println(name));

  }

/**
* 通用的处理逻辑
* @param source 源数据
* @param tester 通用规则校验函数接口
* @param mapper Funtion mapper,具体请参见function源码,接收一个参数,并返回结果
* @param block
*/
public static <X, Y> void processElements(
    Iterable<X> source,
    Predicate<X> tester,
    Function <X, Y> mapper,
    Consumer<Y> block) {

  for (X p : source) {
    if (tester.test(p)) {
    Y data = mapper.apply(p);
    block.accept(data);
  }
}

}

}

interface Predicate<T> {
  public boolean test(T t);
}

方法九:

/**
* 方法九:Stream操作,也就是聚集操作(aggregate operations)
*
* 先看下面的例子,小伙伴惊呆了么? 神奇的jdk8~
*
* 简单来说,下面的处理通过对集合进行了stream处理; stream 就是集合元素的序列,和Collection不同,stream不是用来存储数据的数据结构,它是通过管道(pipeline)从数据源获取数据。
* pipeline是stream操作的序列,比如本例子中的 filter-map-foreach。 换言之,数据仍然是保存在集合中,聚集操作需要数据时实时获取
*
* 题外话:collection 除了扩展stream之外,还新增了spliterator parallelStream两个方法,感兴趣的同学,巴拉巴拉源码或者debug下本示例进行了解吧~
*
* 到这里lambda表达式入门总算结束了,希望这个专题让大家认识了jdk8的新成员——lambda表达式
* (~ o ~)~zZ 好书湖啦~
*
*
* @author zhuotao
*
*/
public class Approach9 {

  public static void main(String[] args) {

    List<Person> persons = PersonGenerator.generatePerons();
    persons
      .stream() // * Returns a sequential {@code Stream} with this collection as its source.
      .filter(p -> p.getAge() > 30 && p.getAge() < 50) //Returns a stream consisting of the elements of this stream that match the given predicate.
      .map(p -> p.getName()) // Returns a stream consisting of the results of applying the given function to the elements of this stream.
      .forEach(name -> System.out.println(name)); // Performs an action for each element of this stream.

  }

}

interface Predicate<T> {
  public boolean test(T t);
}

jdk8新特性之lambda expressions的更多相关文章

  1. JDK8新特性之一Lambda

    JDK8的新特性之一Lambda能将函数作为方法里面的参数使用. /** * JDK8新特性Lambda */ public class Test { public static void main( ...

  2. JDK8新特性(一) Lambda表达式及相关特性

    函数式接口 函数式接口是1.8中的新特性,他不属于新语法,更像是一种规范 面向对象接口复习 在这里先回顾一下面向对象的接口,创建接口的关键字为interface,这里创建一个日志接口: public ...

  3. 1.8 新特性之 Lambda Expressions

    Lambda expressions are allowed only at source level 1.8 or above The target type of this expression ...

  4. JDK8新特性之Lambda表达式

    Lambda表达式主要是替换了原有匿名内部类的写法,也就是简化了匿名内部类的写法.lambda语法结构: (参数1,参数2...)->{重写方法的内容,不定义方法名} 先看一个使用匿名内部类定义 ...

  5. JDK8新特性02 Lambda表达式02_Lambda语法规则

    //函数式接口:只有一个抽象方法的接口称为函数式接口. 可以使用注解 @FunctionalInterface 修饰 @FunctionalInterface public interface MyF ...

  6. JDK8新特性01 Lambda表达式01_设计的由来

    1.java bean public class Employee { private int id; private String name; private int age; private do ...

  7. jdk8新特性--使用lambda表达式的延迟执行特性优化性能

    使用lambda表达式的延迟加载特性对代码进行优化:

  8. JDK8新特性03 Lambda表达式03_Java8 内置的四大核心函数式接口

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.functio ...

  9. JDK8新特性:Lambda表达式

    Lambda表达式,案例一:new Thread(() -> System.out.println("thread")); Lambda表达式,案例二:由参数/箭头和主体组成 ...

随机推荐

  1. UVALive 4957 Fake scoreboard

    题意就是有n个队伍和m个题目 给出了每个队伍解决的题目数量 每个题目也给出了被解决的次数 然后求一个方阵. N,Y表示每个队伍是否过了哪个题目. 要求字典序最小. 这题给人的第一反应就是网络流. 虽然 ...

  2. JavaScript实现自定义短信模板

    自定义短信模板,要求:可以插入关键字,当然是可以在点击到文本域中的任意位置,关键字以中括号包裹的形式出现[关键字],删除关键字要整个关键都删掉,而不是自己全删除. 详细在简书中 http://www. ...

  3. BitBlt介绍

    设备上下文画图有非常多种方法.比如通过创建位图画刷,利用其填充一个区域来实现图像的绘制.此外,还能够使用CDC类的位图函数来输出位图到设备上下文中. BitBlt 用于从原设备中复制位图到目标设备,语 ...

  4. 转载:c++内存泄露机制

    对于一个c/c++程序猿来说,内存泄漏是一个常见的也是令人头疼的问题.已经有很多技术被研究出来以应对这个问题,比方 Smart Pointer,Garbage Collection等.Smart Po ...

  5. duilib DirectUI库里面的一个简单的例子RichListDemo

    1.首先来看这里的CRichListWnd 已经不再是从CWindowWnd继承了 classCRichListWnd:publicWindowImplBase 从WindowImplBase中,可以 ...

  6. JSP九个隐式对象及作用域

    out:JspWriter实例对象,作用域为page(页面执行期) 向客户端输出内容 request:HttpServletRequest实例对象,作用域为request(用户请求期) 请求信息 re ...

  7. Android 网络编程与通信协议

    大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,而Android中主要提供了两种方式来进行HTTP操作, HttpURLConnection和HttpClient.这两种方式都 ...

  8. Android - 消息机制与线程通信

    以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...

  9. spring01

                                                                       spring的体系结构图 第一个spring入门例子 01.创建一 ...

  10. 新浪微博开放平台OAuth授权解决方案(含代码)

    前几日一位朋友项目中需要使用新浪微博的接口,故和这位朋友一同研究了新浪微博开放平台上面所提供的资料,首先要使用这些接口是需要用户登录并且授权的,新浪微博开放平台其实是提供两种授权方式的,第一种是:OA ...