您好,我是湘王,這是我的博客園,歡迎您來,歡迎您再來~
Lambda運算式雖然將介面作為代碼塊賦值給了變數,但如果僅僅只是Lambda運算式,還無法讓Java由量變引起質變,真正讓Lambda能夠發揮出巨大威力的,就是流式計算,
所謂流式計算,就是讓資料像在流水線上一樣,從一道工序流轉到下一道工序,就像這樣:

如果把資料處理的方式比作流水線,那么Spark、Storm和Flink就是目前市面上頭部的三家工廠,它們有各種各樣的資料裝配間(也就是各種處理資料的算子),將資料按照所需加工成型,所以,不懂流式計算根本就做不了大資料開發,上面那張圖,如果換成流式計算的,就是這樣:

Lambda運算式就變成了一個個的資料裝配間,
還是以實際的代碼例子來說明,假如有這樣的代碼:
/**
* 雇員資料
*
* @author 湘王
*/
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;
}
}
如果想篩選28歲以下的員工,并按年齡排序,用老辦法只能這么做:
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)
);
// 傳統篩選資料的方法
// 篩選28歲以下的員工
List<Employee> list1 = new ArrayList<>();
for(Employee employee : employees) {
if (employee.getAge() < 28) {
list1.add(employee);
}
}
// 按年齡排序
list1.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
如果要轉換成Lmabda運算式的話,就是這樣:
/**
* 雇員函式式介面
*
* @author 湘王
*/
@FunctionalInterface
public interface EmployeeInterface<T> {
boolean select(T t);
}
public static List<Employee> filter(List<Employee> employees, EmployeeInterface<Employee> ei) {
List<Employee> list = new ArrayList<>();
for(Employee employee : employees) {
if (ei.select(employee)) {
list.add(employee);
}
}
return list;
}
// 使用Lambda運算式得到28歲以下的員工
List<Employee> list2 = filter(employees, employee -> employee.getAge() < 28);
// 按年齡排序
list2.sort((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
可以看到,這雖然用了Lambda運算式替代了舊的方法,但可能要寫大量的函式式介面,Lambda淪為雞肋,完全談不上簡便快速,更別說優雅!
所以,這時候如果用流式計算,那簡直不要太優雅:
// Lambda運算式 + 流式計算
List<Employee> list3 = employees
// 生成「流」
.stream()
// 過濾
.filter(emp -> emp.getAge() < 28)
// 排序
.sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge()))
// 生成新的結果集合
.collect(Collectors.toList());
僅僅幾行代碼就搞定了,完全沒有之前那種「傻大黑粗」的感覺了,
上面的代碼,可以用這幅圖來還原:

1、先用filter算子(流式計算中的函式,或者方法,在大資料中統稱為算子,我也習慣這么稱呼)將符合年齡條件的雇員篩選出來;
2、再按照年齡從低到高排序;
3、將排好序的員工串列輸出出來,
就是這么簡單粗暴!
就像藏寶圖一樣,只有將Lambda運算式和流式計算這兩張碎片拼起來,才是完整的Java函式式編程,
所有的流式計算算子可以分為兩大類:中間操作和終端操作,
1、中間操作:回傳另一個流,如filter、map、flatMap等;
2、終端操作:從流水線中生成結果,如collect、count、reduce、forEach等,
現在,咱們已經找到了函式式編程這個寶藏,那么再回到最初的問題:當要實作某寶、某東和某哈哈的員工聯誼并解決單身問題時,有更好的辦法嗎?
當然有,而且只用一行代碼就可以搞定:
List<Employee> unMarriedList4 = list.stream().filter(company -> Company.Type.BIG == company.getType()).flatMap(companys -> companys.getEmployees().stream()).filter(Employee::isMarried).sorted(Comparator.comparing(Employee::getAge)).collect(Collectors.toList());
感謝您的大駕光臨!咨詢技術、產品、運營和管理相關問題,請關注后留言,歡迎騷擾,不勝榮幸~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/528116.html
標籤:Java
