jdk8新特性之lambda expressions

本文分兩部分:html

  1. 語法簡單說明
  2. lambda的使用

注:這兩部份內容均以類+註釋的方式進行說明,而且內容均來自官方教程(https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)。java

 

第一部分:express

/**
* 語法說明類
*
* lambda表達式包含下面幾個要素:
* 一、逗號分隔的參數列表,如CheckPerson。test(Person p),其中p表示一個Person的對象實例
* 二、向右箭頭 →, 箭頭左側是表達式入參,箭頭右側是表達式自己
* 三、表達式體,包含單個表達式或者一個語句塊
*
* @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);
  }
}
}oracle

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

 

第二部分:ide

假設一種場景:
A正在開發一個社交網絡應用,考慮添加一個功能——管理員能夠根據用戶(Person)的不一樣特徵,執行不一樣的操做,好比發送信息。函數

approaches是A寫的不一樣的實現,從a1 ~ a8,看看每一個方法較以前有什麼明顯的提高。優化

備註:1> Person 社交網絡應用用戶類  2> PersonGenerator 用戶列表模擬產生類

方法一:

/**
* 方法一:建立一個方法,用於查詢某個特徵的用戶
* 一、方法入參:
* persons 用戶列表
* age 約束條件,最低年齡
* 二、輸出打印知足條件的用戶信息
*
* 不過,總感受有什麼不對,若是有一天功能的約束條件增長該怎麼辦?好比,「同事知足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方法作了什麼?一、接收用戶列表 二、規則判斷 三、輸出打印符合條件的用戶信息
* 那若是我有類似的邏輯:好比 一、接收用戶列表(待處理數據) 二、執行某個規則(lambda表達式) 三、發送用戶信息(操做) 該如何操做呢?
* 這裏仍是以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);}

相關文章
相關標籤/搜索