java8新特性之Stream API

java8新特性之Stream API

瞭解Stream

Java8中有兩大最為重要的改變。第一個是 Lambda 表達式;另外個則是 Stream API(java.util.stream.*)


定義:Stream是數據渠道,用於操作數據源(集合、數組等)所生成的元素序列。“集合講的是數據,流講的是計算!”

注意:

①Stream 自己不會存儲元素

②Stream 不改變源對象。相反,他們會返回一個持有結果的新Stream

③Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行。(在使用Stream API時如果沒有終止操作,代碼不會執行)



Stream API 的操作步驟:

  1. 創建 Stream
  2. 中間操作
  3. 終止操作(終端操作)
java8新特性之Stream API



創建 Stream,4種方法

  • Collection 提供了兩個方法 stream() 與 parallelStream()
 List<string> list = new ArrayList<>();
Stream<string> stream = list.stream(); //獲取一個順序流
Stream<string> parallelStream = list.parallelStream(); //獲取一個並行流

/<string>/<string>/<string>
  • 通過 Arrays 中的 stream() 獲取一個數組流
 Integer[] nums = new Integer[10];
Stream<integer> stream1 = Arrays.stream(nums);

/<integer>
  • 通過 Stream 類中靜態方法 of()
 Stream<integer> stream2 = Stream.of(1,2,3,4,5,6);

/<integer>
  • 創建無限流
 //迭代
//解析該方法:iterate(final T seed, final UnaryOperator f)
//第一個參數:seed 為迭代的起始種子(起始數)

//第二個參數:UnaryOperator則是一個函數式接口,對傳入參數進行一元運算(x+2就是函數接口方法的具體實現)
//.limit(10)是中間操作
Stream<integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
stream3.forEach(System.out::println);

/<integer>


中間操作:多個中間操作可以連接起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理而在終止操作時一次性全部處理,稱為“惰性求值”


篩選與切片

java8新特性之Stream API

以limit()方法為例進行解釋

//如果有limit方法,因為Stream是延遲執行的,所以只有當e.getSalary() >= 5000;滿足時
//才會打印輸出語句,節省內存空間
public void test4(){
emps.stream()
.filter((e) -> {
System.out.println("短路!"); // && ||
return e.getSalary() >= 5000;
}).limit(3)
.forEach(System.out::println);
}

映射

java8新特性之Stream API

比較map()方法和flatMap()方法的區別:前者是將獲得的元素的流以流的形式放入總的流中,後者則是將流中的元素單獨拿出來放入總的流中。(以下代碼,前者的返回值是嵌套的,後者則是總流)

//TestStreamAPI1是類名
//類中的靜態方法,傳入字符串返回拆分後字符數組的流
public static Stream<character> filterCharacter(String str){
List<character> list = new ArrayList<>();

for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
public void test1(){

List<string> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");

Stream<stream>> stream2 = strList.stream()
.map(TestStreamAPI1::filterCharacter);

stream2.forEach((sm) -> {
sm.forEach(System.out::println);
});

System.out.println("---------------------------------------------");

Stream<character> stream3 = strList.stream()
.flatMap(TestStreamAPI1::filterCharacter);

stream3.forEach(System.out::println);
}
/<character>/<stream>/<string>/<character>/<character>

排序

java8新特性之Stream API



Stream 的終止操作

查找和匹配

java8新特性之Stream API

java8新特性之Stream API

樣例代碼

//findAny()方法
Optional<employee> op2 = emps.parallelStream()
.filter((e) -> e.getStatus().equals(Status.FREE))
.findAny();
System.out.println(op2.get());
//min()方法
Optional<employee> op2 = emps.stream()
.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op2.get());
/<employee>/<employee>

歸約

java8新特性之Stream API

代碼

//reduce() 方法,第一個參數為起始值
//第二個參數:BinaryOperator 是一個函數式接口,功能是傳入兩個參數,並對其進行操作,返回出來
//reduce()方法運行順序,將“0”作為起始值傳給“x”,數組中去第一個值傳給“y”,相加得值再賦值給“x”,數組中取第二個值賦值“y”,相加.....以此類推
public void test1(){
List<integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
}
/<integer>

收集

java8新特性之Stream API

List<employee> emps = Arrays.asList(
new Employee(102, "李四", 79, 6666.66, Status.BUSY),
new Employee(101, "張三", 18, 9999.99, Status.FREE),
new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
);
//求實例總數
Long count = emps.stream()
.collect(Collectors.counting());
/<employee>

Collector 接口中方法的實現決定了如何對流執行收集操作(如收集到 List、Set、Map)。但是 Collectors 實用類提供了很多靜態方法,可以方便地創建常見收集器實例,具體方法與實例如下表:

java8新特性之Stream API

java8新特性之Stream API

java8新特性之Stream API

java8新特性之Stream API

代碼實例

//多級分組
//先按狀態分組(status),然後再自定義按年齡分組
@Test
public void test6(){
Map<status>>> map = emps.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if(e.getAge() >= 60) {
return "老年";
} else if(e.getAge() >= 35) {
return "中年";
} else {
return "成年";
}
})));


System.out.println(map);
}
/<status>


並行流與串行流並行流

就是把一個內容分成多個數據塊,並用不同的線程分別處理每個數據塊的流。(底層使用Fork/Join 框架)

Java 8 中將並行進行了優化,我們可以很容易的對數據進行行操作。Stream API 可以聲明性地通過 parallel() 與sequential() 在並行流與順序流之間進行切換。

Long sum = LongStream.rangeClosed(0L, 10000000000L)
.parallel()
.sum();


容器類(Optional類)

Optional 類(java.util.Optional) 是一個容器類,代表一個值存在或不存在,原來用 null 表示一個值不存在,現在 Optional 可以更好的表達這個概念。並且可以避免空指針異常。(將實例外面再套一個容器)

java8新特性之Stream API


分享到:


相關文章: