Stream流式思想概述
/**
* 用傳統(tǒng)的方式,遍歷集合,對集合中的數(shù)據(jù)進(jìn)行過濾
*/
public class Demo10Stream {
public static void main(String[] args) {
//創(chuàng)建一個list集合,存儲姓名
List<String> list = new ArrayList<>();
list.add("張無忌");
list.add("周芷若");
list.add("趙敏");
list.add("張墻");
list.add("張三豐");
//對list集合中的元素進(jìn)行排序,只要以張開頭的元素,存儲到一個新的集合中
List<String> listA = new ArrayList<>();
for(String s : list){
if(s.startsWith("張")){
listA.add(s);
}
}
//對listA集合進(jìn)行過濾,只要姓名長度為3的人,存儲到一個新的集合中
List<String> listB = new ArrayList<>();
for(String s : listA){
if(s.length() == 3){
listB.add(s);
}
}
//遍歷listB集合
for(String s:listB){
System.out.println(s);
}
}
}
import java.util.ArrayList;
import java.util.List;
/**
* 用Stream流的方式,遍歷集合,對集合中的數(shù)據(jù)進(jìn)行過濾
* Stream關(guān)注的是做什么,而不是怎么做
*/
public class Demo10Stream1 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("張無忌");
list.add("周芷若");
list.add("趙敏");
list.add("張墻");
list.add("張三豐");
//對list集合中的元素進(jìn)行排序,只要以張開頭的元素,存儲到一個新的集合中
//對listA集合進(jìn)行過濾,只要姓名長度為3的人,存儲到一個新的集合中
//遍歷listB集合
list.stream()
.filter(name->name.startsWith("張"))
.filter(name->name.length()==3)
.forEach(name-> System.out.println(name));//兩次過濾,一次輸出
}
}
Stream流是一個來自數(shù)據(jù)源的元素隊(duì)列。
數(shù)據(jù)源可以是集合,數(shù)組等。
兩個基本特征:
(1)Pipelining:中件的操作都返回流本身,這樣多個操作可以串聯(lián)成一個管道。
(2)內(nèi)部迭代:以前對集合遍歷都是通過Iterator或增強(qiáng)for的方式,顯示的在集合外部進(jìn)行迭代,這叫外部迭代。Stream提供了內(nèi)部迭代的方式,流可以直接調(diào)用遍歷方法。
當(dāng)使用一個流的時候,通常包括三個基本步驟:獲取一個數(shù)據(jù)源-》數(shù)據(jù)轉(zhuǎn)換-》執(zhí)行操作獲取想要的結(jié)果,每次轉(zhuǎn)換原油Stream對象不改變,返回一個新的Stream對象(可以有多次轉(zhuǎn)換),這就允許對其操作可以像鏈條一樣排列,變成一個管道。
兩種獲取Stream流的方式
java.util.stream.Stream<T>是Java8新加入的最常用的流接口(并不是函數(shù)式接口)
(1)所有的Collection集合都可以通過stream默認(rèn)方法獲取流;
(2)stream接口的靜態(tài)方法of可以獲取數(shù)組對應(yīng)的流。
public static void main(String[] args) {
//把集合轉(zhuǎn)換為Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String, String> map = new HashMap<>();
//獲取鍵,存儲到一個set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//獲取值,存儲到一個Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//獲取鍵值對(鍵與值的映射關(guān)系entryset)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
//把數(shù)組轉(zhuǎn)換為Stream流
Stream<Integer> stream6 = Stream.of(1,2,3,4,5);
//可變參數(shù)可以傳遞數(shù)組
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a", "bb", "ccc"};
}
常用方法:
方法被分為兩種:
(1)延遲方法:返回值類型仍然是Stream接口自身類型的方法,因此支持鏈?zhǔn)秸{(diào)用(除了終結(jié)方法外,其余方法均為延遲方法)。
(2)終結(jié)方法:返回值類型不再是Stream接口自身類型的方法,因此不再支持類似StringBuilder那樣的鏈?zhǔn)秸{(diào)用。終結(jié)方法包括count和forEach方法。
forEach方法:
import java.util.stream.Stream;
/**
* forEach()接受一個Consumer接口函數(shù),是一個消費(fèi)型接口,可以傳遞lambda表達(dá)式,消費(fèi)數(shù)據(jù)
* forEach方法用來遍歷流中的數(shù)據(jù),是一個終結(jié)方法,遍歷之后就不能繼續(xù)調(diào)用Stream流中的其他方法
* */
public class Demo01ForEach {
public static void main(String[] args) {
//獲取Stream流
Stream<String> stream = Stream.of("張三","李四","王五","趙六","田七");
//使用Stream流中的方法forEach對Stream流中的數(shù)據(jù)進(jìn)行遍歷
stream.forEach((String name)->{
System.out.println(name);
});
}
}
filter方法:
import java.util.stream.Stream;
/**
* Stream流中的常用方法filter:用于對Stream流中的數(shù)據(jù)進(jìn)行過濾
* filter方法的參數(shù)Predicate是一個函數(shù)式接口,所以可以傳遞lambda表達(dá)式,對數(shù)據(jù)進(jìn)行過濾
*/
public class Demo02Filter {
public static void main(String[] args) {
//創(chuàng)建一個Stream流
Stream<String> str = Stream.of("張三豐", "張翠山","趙敏","周芷若","張無忌");
//對Stream流中的元素進(jìn)行過濾,只要姓張的人
Stream<String> stream2 = str.filter((String name)->{return name.startsWith("張");});
stream2.forEach(name -> System.out.println(name));
}
}
/**
* Stream流屬于管道流,只能被消費(fèi)(使用)一次
* 第一個Stream流調(diào)用完畢方法,數(shù)據(jù)就會流轉(zhuǎn)到下一個Stream上,
* 而這時第一個stream流已經(jīng)使用完畢,就會關(guān)閉了
* 所以第一個Stream流就不能再調(diào)用方法了
*/
映射map方法:
如果需要將流中的元素映射到另一個流中,就可以使用map方法
import java.util.stream.Stream;
public class Demo03Stream_map {
public static void main(String[] args) {
//獲取一個String類型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//使用map方法,把字符串類型的整數(shù),轉(zhuǎn)換為Integer類型的整數(shù)
Stream<Integer> stream2 = stream.map((String s)->{
return Integer.parseInt(s);
});
//遍歷stream2流
stream2.forEach(i-> System.out.println(i));
}
}
count方法:
用于統(tǒng)計stream流中元素的個數(shù)
count方法是一個終結(jié)方法,返回值是一個long類型的整數(shù),所以不能再繼續(xù)調(diào)用Stream流中的其他方法了。
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);
}
取用前幾個limit方法:
/**
* limit是一個延遲方法,只是對流中的元素進(jìn)行截取,返回的是一個新的流,所以可以繼續(xù)調(diào)用Stream流中的其他方法
*/
public class Demo05Stream_limit {
public static void main(String[] args) {
//獲取一個Stream流
String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
Stream<String> stream = Stream.of(arr);
//使用limit對Stream流中的元素進(jìn)行截取,只要前三個元素
Stream<String> stream2 = stream.limit(3);
//遍歷stream2流
stream2.forEach(name-> System.out.println(name));
}
}
跳過前幾個skip方法:
String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
Stream<String> stream = Stream.of(arr);
//使用skip跳過前3個元素
Stream<String> stream1 = stream.skip(3);
stream1.forEach(name-> System.out.println(name));
}