Stream流
1.8 java推出的新特性
- Stream流的出現,可以讓我們
,使得減少代碼量
,同時會使得代碼更加的優雅
代碼不易閱讀
傳統寫法與Stream流的比較
使用傳統的寫法:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("李四");
list.add("王五");
//周遊
for(String name : list){
System.out.println(name);
}
這樣會輸出
使用Stream的寫法:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("李四");
list.add("王五");
//周遊
list.stream().forEach(name-> System.out.println(name));
同樣會輸出
或許這樣還不太容易看得出變得更加友善了…
提出一個新的需求
1. 對list集合中的元素進行過濾,隻要以張開頭的元素,存儲到一個新的集合A中
2. 并且要求隻要姓名長度為三的人,存儲到一個新集合B中
3. 周遊新集合B
- 使用傳統的寫法:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("張三豐");
list.add("李白");
list.add("李清照");
list.add("周傑倫");
list.add("張老頭");
//對list集合中的元素進行過濾,隻要以張開頭的元素,存儲到一個新的集合中
List<String> listA = new ArrayList<>();
for(String name : list){
if(name.startsWith("張")){
listA .add(name);
}
}
//隻要姓名長度為三的人,存儲到一個新集合中
List<String> listB = new ArrayList<>();
for(String name: listA){
if(name.length() == 3){
listB.add(name);
}
}
//周遊2的新集合
for(String name: listB){
System.out.println(name);
}
輸出結果:
- 使用Stream的寫法:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("張三豐");
list.add("李白");
list.add("李清照");
list.add("周傑倫");
list.add("張老頭");
//對list集合中的元素進行過濾,隻要以張開頭的元素,存儲到一個新的集合中
//隻要姓名長度為三的人,存儲到一個新集合中
//周遊新集合
list.stream()
.filter(name->name.startsWith("張"))
.filter(name->name.length() == 3)
.forEach(name->System.out.println(name));
輸出結果同樣是
通過這個列子就能很好的看出Steram流的
代碼量少
,
簡潔
,同時缺點相對于傳統的方法,
代碼變得不易閱讀
如何擷取Stream流
- 一. 可以通過API文檔在
找到它的java.util.stream
接口,使用靜态方法of來進行擷取Interface Stream<T>
Stream<String> stream1 = Stream.of("張三","李四","王五");
Stream<Integer> stream2 = Stream.of(1,2,3);
//使用數組擷取Stream流
String[] str = {"張三","李四","王五"};
stream3 = Stream.of(str);
Integer[] in = {1,2,3};
stream3 = Stream.of(in);
- 二.把集合轉換成Stream流
//可以改成Integer等别的類型
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
//map隻能進行轉換然後存取
Map<String,String> map = new HashMap<>();
//1. 換取鍵,存儲到Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//2. 擷取值,存儲到Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//3. 擷取鍵值對(鍵與值的映射關系 enterSet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
Stream流的一些常用的方法
- forEach: 周遊
Stream<T> forEach(Consumer<? super T> action)
Consumer<? super T> action 是一個抽象方法,用于消費的
由于是抽象方法是以我們可以使用lambda表達式
例子:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("李四");
list.add("王五");
//周遊
list.stream().forEach(name-> System.out.println(name));
//name-> System.out.println(name)是一個lambda表達式
結果:
- filter: 是否比對(條件)
Stream<T> filter(Predicate<? super T> predicate)
Predicate<? super T> predicate 是一個抽象方法 傳回的是一個boolean值
例子:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("李四");
list.add("張三豐");
list.add("花無缺");
//開頭是否有張
//姓名是否三個字
list.stream().filter(name->name.startsWith("張"))
.filter(name->name.length() == 3)
.forEach(name->System.out.println(name));
//以下都是lambda表達式
//name->name.startsWith("張") startsWith方法是測試此字元串是否以指定的字首開頭。
//name->name.length() == 3
//name->System.out.println(name)
輸出結果
- map: 轉換資料類型
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Function<? super T,? extends R> mapper 是一個抽象方法,可以把參數1轉換成參數2的資料類型
例子:
//擷取一個String類型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//将String類型轉換成Integer類型,不僅可以轉換成Integer類型也可以轉換成對象
Stream<Integer> stream2 = stream.map(s->Integer.parseInt(s));
//周遊stream2
stream2.forEach(in-> System.out.println(in));
//其實也可以連着寫
//stream.map(s->Integer.parseInt(s)).forEach(in-> System.out.println(in));
以下都是lambda表達式
//s->Integer.parseInt(s)
//in-> System.out.println(in)
輸出結果:
- count: 擷取數量
例子:
//建立一個集合
List<String> list = new ArrayList<>();
//添加
list.add("張三");
list.add("李四");
list.add("張三豐");
list.add("花無缺");
//擷取數量
long count = list.stream().count();
System.out.println(count);
輸出結果:
- limit: 截取
例子:
String[] str = {"張三","李四","王五","趙六","田七"};
Stream<String> stream = Stream.of(str);
Stream<String> stream2 = stream.limit(3); //截取1-3的資料
stream2 .forEach(str->System.out.println(str));
結果:
- skip: 用來跳過元素
例子:
String[] str = {"張三","李四","王五","趙六","田七"};
Stream<String> stream = Stream.of(str);
Stream<String> stream2 = stream.skip(3); //跳過前3個
stream2 .forEach(name->System.out.println(name));
結果:
7. concat:
<R,A> R collect(Collector<? super T,A,R> collector)
Collector<? super T,A,R> collector
是一個抽象方法,可以将兩個stream流連接配接起來
例子:
String[] str1 = {"張三","李四","王五","趙六","田七"};
String[] str2 = {"李白","杜甫","王安石","白居易"};
Stream<String> stream1 = Stream.of(str1);
Stream<String> stream2 = Stream.of(str2);
Stream<String> stream = Stream.concat(stream1,stream2);
stream.forEach(name->System.out.println(name));
結果:
注意:
- Stream流使用一次後,就會關閉,如果重新使用就會報錯(
Stream流隻能使用一次
)
例如:
String[] str = {"張三","李四","王五","趙六","田七"};
Stream<String> stream = Stream.of(str);
//使用第一次
stream.skip(1);
//使用第二次
stream.forEach(name-> System.out.println(name));
報錯:
IllegalStateException: stream has already been operated upon or closed