1.Stream流
1.1兩種獲取流的方法
java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(這並不是一個函數式接口。)
獲取一個流非常簡單,有以下幾種常用的方式:
所有的 Collection 集合都可以通過 stream 默認方法獲取流;
Stream 接口的靜態方法 of 可以獲取數組對應的流。
根據Collection獲取流
import java.util.*; import java.util.stream.Stream; public class Demo04GetStream { public static void main(String[] args) { List<String> list = new ArrayList<>(); // ... Stream<String> stream1 = list.stream(); Set<String> set = new HashSet<>(); // ... Stream<String> stream2 = set.stream(); Vector<String> vector = new Vector<>(); // ...
Stream<String> stream3 = vector.stream();
}
}
根據Map獲取流 import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; public class Demo05GetStream { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); // ... Stream<String> keyStream = map.keySet().stream(); Stream<String> valueStream = map.values().stream(); Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream(); } }
根據數組獲取流 如果使用的不是集合或映射而是數組,由於數組對象不可能添加默認方法,所以 Stream 接口中提供了靜態方法 of ,使用很簡單: import java.util.stream.Stream; public class Demo06GetStream { public static void main(String[] args) { String[] array = { "張無忌", "張翠山", "張三豐", "張一元" }; Stream<String> stream = Stream.of(array); }
1.2常用方法
流模型的操作很豐富,這里介紹一些常用的API。這些方法可以被分成兩種:
延遲方法:返回值類型仍然是 Stream 接口自身類型的方法,因此支持鏈式調用。(除了終結方法外,其余方
法均為延遲方法。)
終結方法:返回值類型不再是 Stream 接口自身類型的方法,因此不再支持類似 StringBuilder 那樣的鏈式調
用。本小節中,終結方法包括 count 和 forEach 方法。
逐一處理 void forEach(Consumer<? super T> action); 過濾 Stream<T> filter(Predicate<? super T> predicate); 映射 <R> Stream<R> map(Function<? super T, ? extends R> mapper); 統計個數 long count(); 取用前幾個 Stream<T> limit(long maxSize); 跳過前幾個 Stream<T> skip(long n); 組合 static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
1.3練習:集合元素處理
現在有兩個 ArrayList 集合存儲隊伍當中的多個成員姓名,要求使用傳統的for循環(或增強for循環)依次進行以
下若干操作步驟:
1. 第一個隊伍只要名字為3個字的成員姓名;存儲到一個新集合中。
2. 第一個隊伍篩選之后只要前3個人;存儲到一個新集合中。
3. 第二個隊伍只要姓張的成員姓名;存儲到一個新集合中。
4. 第二個隊伍篩選之后不要前2個人;存儲到一個新集合中。
5. 將兩個隊伍合並為一個隊伍;存儲到一個新集合中。
6. 根據姓名創建 Person 對象;存儲到一個新集合中。
7. 打印整個隊伍的Person對象信息。
兩個隊伍(集合)的代碼如下:
import java.util.ArrayList; 而 Person 類的代碼為: import java.util.List; public class DemoArrayListNames { public static void main(String[] args) { //第一支隊伍 ArrayList<String> one = new ArrayList<>(); one.add("迪麗熱巴"); one.add("宋遠橋"); one.add("蘇星河"); one.add("石破天"); one.add("石中玉"); one.add("老子"); one.add("庄子"); one.add("洪七公"); //第二支隊伍 ArrayList<String> two = new ArrayList<>(); two.add("古力娜扎"); two.add("張無忌"); two.add("趙麗穎"); two.add("張三豐"); two.add("尼古拉斯趙四"); two.add("張天愛"); two.add("張二狗"); // .... } }
而 Person 類的代碼為:
public class Person { private String name; public Person() {} public Person(String name) { this.name = name; } @Override public String toString() { return "Person{name='" + name + "'}"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
解答:
import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class DemoStreamNames { public static void main(String[] args) { List<String> one = new ArrayList<>(); // ... List<String> two = new ArrayList<>(); // ... // 第一個隊伍只要名字為3個字的成員姓名; // 第一個隊伍篩選之后只要前3個人; Stream<String> streamOne = one.stream().filter(s ‐> s.length() == 3).limit(3); // 第二個隊伍只要姓張的成員姓名; // 第二個隊伍篩選之后不要前2個人; Stream<String> streamTwo = two.stream().filter(s ‐> s.startsWith("張")).skip(2); // 將兩個隊伍合並為一個隊伍; // 根據姓名創建Person對象; // 打印整個隊伍的Person對象信息。 Stream.concat(streamOne, streamTwo).map(Person::new).forEach(System.out::println); }}
運行效果:
Person{name='宋遠橋'}
Person{name='蘇星河'}
Person{name='石破天'}
Person{name='張天愛'}
Person{name='張二狗'}
2.方法引用
在使用Lambda表達式的時候,我們實際上傳遞進去的代碼就是一種解決方案:拿什么參數做什么操作。那么考慮
一種情況:如果我們在Lambda中所指定的操作方案,已經有地方存在相同方案,那是否還有必要再寫重復邏輯?
雙冒號 :: 為引用運算符,而它所在的表達式被稱為方法引用。如果Lambda要表達的函數方案已經存在於某個方
法的實現中,那么則可以通過雙冒號來引用該方法作為Lambda的替代者。
2.1 通過對象名引用成員方法

2.2 通過類名稱引用靜態方法

2.3 通過super引用成員方法



2.4 通過this引用成員方法


2.5 類的構造器引用


2.6 數組的構造器引用


