Java 8 中,得益於 lambda
帶來的函數式編程,引入了一個全新的 Stream流
概念,用於解決集合已有的弊端。java
咱們先來看一個例子:編程
篩選出 names 中以 '張' 開頭的字符串獲得子集1,再篩選出 子集1 中長度爲 3 的字符串,而後遍歷輸出。數組
// 傳統集合的方式
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("張三丰");
names.add("張大寶");
names.add("張三");
names.add("德瑪傑");
names.add("喬峯");
names.add("李大寶");
List<String> list1 = new ArrayList<>(); //以 '張' 開頭的字符串
for (String name:names){
if (name.startsWith("張")){
list1.add(name);
}
}
List<String> list2 = new ArrayList<>(); // list1中長度爲 3 的字符串
for (String name:list1){
if (name.length()==3){
list2.add(name);
}
}
for (String name:list2){
System.out.println(name);
}
}
複製代碼
// stream流方式
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("張三丰");
names.add("張大寶");
names.add("張三");
names.add("德瑪傑");
names.add("喬峯");
names.add("李大寶");
names.stream().filter(name->name.startsWith("張"))
.filter(name->name.length()==3).forEach(System.out::println);
}
複製代碼
能夠看到用 stream
流方式比傳統集合的方式精簡了不少。bash
Collection
集合能夠經過 stream()
方法獲取流.Stream
類的靜態方法 of()
一般用於將數組轉成 stream
流。public static void main(String[] args) {
// 集合轉成 stream 流
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set<Integer> set = new HashSet<>();
Stream<Integer> setStream = set.stream();
// 數組轉成 stream 流
String[] names = new String[]{"zs","ls","ww"};
Stream<String> namesStream = Stream.of(names);
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
}
複製代碼
stream
流中方法分爲兩類:app
Stream
類型Stream
類型,例如: count()
和 forEach()
。filter()
將一個流轉換成另一個子流,該方法接受一個 Predicate 類型的參數
(系統內置函數接口之一)。函數式編程
Stream<T> filter(Predicate<? super T> predicate);
函數
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("張三丰");
names.add("張大寶");
names.add("張三");
names.add("德瑪傑");
names.add("喬峯");
names.add("李大寶");
// 過濾 names 集合,只要姓張的人,而後輸出
names.stream().filter(name->name.startsWith("張")).
forEach(System.out::println);
}
複製代碼
Stream
流屬於管道流,只能被使用一次,當一個 Stream
流調用了終結方法後,就會被關閉,再次調用其方法會報錯。spa
public static void main(String[] args) {
// 數組轉成 stream 流
String[] names = new String[]{"zsf","ls","ww"};
Stream<String> namesStream = Stream.of(names);
namesStream.filter(name->name.length()==3).
forEach(System.out::println);
// 流已經被關閉,再次調用
namesStream.forEach(System.out::println);
}
複製代碼
若是須要將流中的元素映射到另外一個流中,能夠用 map()
方法,通常用於將一種類型的數據轉成另外一種類型的數據。code
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
複製代碼
public static void main(String[] args) {
// 數組轉成 stream 流
String[] strings = new String[]{"1","2","3"};
Stream<String> stream1 = Stream.of(strings);
// 使用 map 方法,將字符串類型的整數轉成 Integer 類型的整數,而後遍歷
Stream<Integer> stream2 = stream1.map(k->Integer.parseInt(k));
stream2.forEach(System.out::println);
}
複製代碼
limit()
能夠對流中的元素進行截取,只截取前 n 個cdn
public static void main(String[] args) {
// 數組轉成 stream 流
String[] strings = new String[]{"1","2","3","4"};
// 只截取前3個元素,輸出
Stream.of(strings).limit(3).forEach(System.out::println);
}
複製代碼
跳過流中的前 n 個元素,若是 n 大於流中元素的個數,返回一個長度爲 0 的流。
public static void main(String[] args) {
// 數組轉成 stream 流
String[] strings = new String[]{"1","2","3","4"};
// 跳過前2個元素,輸出
Stream.of(strings).skip(2).forEach(System.out::println);
}
複製代碼
Stream
類的靜態方法用於將兩個流合併。
public static void main(String[] args) {
// 數組轉成 stream 流
String[] strings1 = new String[]{"1","2","3","4"};
String[] strings2 = new String[]{"3","4","5","6"};
Stream<String> stream1 = Stream.of(strings1);
Stream<String> stream2 = Stream.of(strings2);
Stream<String> stream3 = Stream.concat(stream1,stream2);
stream3.forEach(System.out::println); // 輸出 1,2,3,4,3,4,5,6
}
複製代碼