Java Stream特性與lambda表示式
古人學問無遺力,少壯工夫老始成
Stream 簡介
Stream 流是jdk1.8版本引進的,那麼Stream主要是對Java中的集合所提出的的集合流抽象工具(java.util.stream),主要用於集合內的元素的計算,準確的說是過濾和統計計算。
lambda簡介
Java9 在語法上提供了Lambda表示式來傳遞方法體,簡化了之前方法必須藏身在不必要的類中的繁瑣。Lambda表示式體現了函數語言程式設計的思想,即一個函式亦可以作為另一個函式引數和返回值,使用了函式作引數/返回值的函式被稱為高階函式。
lambda使用例項
以Runnable介面為例, 如果要執行一個介面,其實就是執行的是run()方法,但是還得需要先建立一個Runnable介面,實現類。
這時候使用lambda就不必了,可以直接執行run()方法。
new Thread(()->System.out.println("Hello world")).start();
Stream流的使用例項
1)對Stream的理解
Stream不是一種真實的資料來源(不存在資料結構),所以我們沒有辦法直接來建立它,Stream只能依賴其他資料來源來轉換成我們的抽象操作。Stream本身是不存在,只是我們抽象出來的一個抽象操作,經過各種操作之後,Stream還需要轉換成真實的資料來源。
而且流是一次性資料,經過一次的中間操作選擇後,就發生改變,如果想對一開始的流操作,需要重新建立一開始的流,因為現在的流已經改變。
如上圖所述,現在的流的內容為(4,8,12)
2)Stream的建立
三中stream的建立方法
//第一種 通過Stream介面的of靜態方法建立一個流 Stream<String> stream = Stream.of("hello", "world", "helloworld"); //第二種 通過Arrays類的stream方法,實際上第一種of方法底層也是呼叫的Arrays.stream(values); String[] array = new String[]{"hello","world","helloworld"}; Stream<String> stream3 = Arrays.stream(array); //第三種 通過集合的stream方法,該方法是Collection介面的預設方法,所有集合都繼承了該方法 Stream<String> stream2 = Arrays.asList("hello","world","helloworld").stream();
接下來看一個簡單的例子
現有 Arrays.asList(1, 2, 3, 4, 5, 6); 一個列表
需求 找出偶數並返回一個新的陣列
傳統做法
public class Test {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
System.out.println(me(list));
}
public static List<Integer>me(List<Integer> list){
ArrayList<Integer> list2 = new ArrayList<>();
for (Integer integer : list) {
if (integer%2==0){
list2.add(integer);
}
}
return list2;
}
}
運用stream來做
public class Test1 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
list.stream().filter(x -> x % 2 == 0).forEach(s-> System.out.println(s));
}
}
用流僅僅一句話,就可以實現,摘出來分析一下。
list.stream() ###建立流物件
list.stream().filter() ##filter 中間操作,相當於過濾器,中間要寫的就是判斷條件
list.stream().filter(x->x%2==0) ##x->x lambda 表示式 x%2==0 判斷條件。
其實,我們發現用stream 其實就是用一些中間操作,要注意這些中間操作,並不是一呼叫就會生效的,只用執行終端操作時,中間的操作才會生效。這就是Stream的延遲特性。
3)stream的中間及其終端操作操作
4)分組例子(groupingBy)
學生類中來自不同地方的學生,有男生也有女生。
需求
現在根據地方分成不同的小組
根據性別分組
用stream流來做
Student類
package com.westos.test;
public class Student {
private String name;
private String sex;
private String loc;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", loc='" + loc + '\'' +
'}';
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public String getLoc() { return loc; }
public void setLoc(String loc) { this.loc = loc; }
public Student(String name, String sex, String loc) {
this.name = name;
this.sex = sex;
this.loc = loc;
}}
實現方法按地區分組
package com.westos.test;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestStudent {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("張", "男", "西安"),
new Student("李", "男", "西安"),
new Student("王", "女", "北京"),
new Student("趙", "女", "上海"),
new Student("周", "男", "北京"));
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student -> Student.getLoc()));
System.out.println(collect);
}
}
執行結果
{上海=[Student{name=‘趙’, sex=‘女’, loc=‘上海’}],
西安=[Student{name=‘張’, sex=‘男’, loc=‘西安’}, Student{name=‘李’, sex=‘男’, loc=‘西安’}],
北京=[Student{name=‘王’, sex=‘女’, loc=‘北京’}, Student{name=‘周’, sex=‘男’, loc=‘北京’}]}
按照性別分組
package com.westos.test;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestStudent {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("張", "男", "西安"),
new Student("李", "男", "西安"),
new Student("王", "女", "北京"),
new Student("趙", "女", "上海"),
new Student("周", "男", "北京"));
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student -> Student.getSex()));
System.out.println(collect);
}
}
執行結果
{女=[Student{name=‘王’, sex=‘女’, loc=‘北京’},
Student{name=‘趙’, sex=‘女’, loc=‘上海’}],
男=[Student{name=‘張’, sex=‘男’, loc=‘西安’},
Student{name=‘李’, sex=‘男’, loc=‘西安’},
Student{name=‘周’, sex=‘男’, loc=‘北京’}]}
5)分割槽例子(partitioningBy)
再剛才的Student例子中再加入成績屬性。
那麼我們要做的是將現有的學生類,按照成績分成兩類,這個時候可以用到分割槽
package com.westos.test;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestStudent {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("張", "男", "西安",89),
new Student("李", "男", "西安",99),
new Student("王", "女", "北京",45),
new Student("趙", "女", "上海",25),
new Student("周", "男", "北京",66));
Map<Boolean, List<Student>> collect = students.stream().collect(Collectors.partitioningBy(s -> s.getSco() >= 50));
List<Student> studentList = collect.get(false);//輸出小於50分的
collect.get(true);//輸出大於等於50分的
System.out.println(studentList);//輸出小於50分的
}
}
結果
[Student{name=‘王’, sex=‘女’, loc=‘北京’, sco=45},
Student{name=‘趙’, sex=‘女’, loc=‘上海’, sco=25}]
總結:
其實分割槽會將我們的stream分成一個集合,集合中有兩個列表,一個是false對應的,也就是低於50分的,另一個就是true對應的列表,也就是大於等於50分的。
那個我們可以將分割槽總結,它就經過條件,將stream分成兩部分,一個是條件成立的,一個是篩選過後的。
6)總結
Stream每個操作都是依賴Lambda表示式或方法引用。
Stream操作是一種宣告式的資料處理方式。
Stream操作提高了資料處理效率、開發效率