引例:
1 List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana"); 2 Stream<String> streamList = strList.stream();//集合轉為stream 3 strList = streamList.distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList()); 4 strList.forEach(System.out::println);
說明:
以上代碼顯示了stream API的方便。當然,上邊的代碼可以更為簡潔,如下改為一行:
Arrays.asList("zhaojigang","nana","tianya","nana").stream().distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList()).forEach(System.out::println);
以上代碼有一個易錯點:filter是選擇而不是過濾,即filter是選擇滿足條件的元素。
一、創建Stream
三種常用API:
1 List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana"); 2 Stream<String> streamList = strList.stream();//集合轉為stream 3 4 String[] strArray = {"java","c++","c"}; 5 Stream<String> streamArray = Stream.of(strArray);//數組轉為Stream 6 Stream<String> streamArray2 = Arrays.stream(strArray);//數組轉為Stream 7 8 Stream<String> streamPartArray = Arrays.stream(strArray, 0, 2);//轉換部分數組,范圍:[0,2) 9 10 Stream<String> streamSelf = Stream.of("python","basic","php");//任意元素
還有一種:用於產生無限流的,Stream.generate(Supplier<T> s)。
二、Stream 2 array/collection/String/map
1、stream2array
1 Stream<String> strStream = Stream.of("java","c++","c","python"); 2 Object[] objectArray = strStream.toArray();//只能返回Object[] 3 String[] strArray = strStream.toArray(String[]::new);//構造器引用(類似於方法引用),可以返回String[]
說明:
通過構造器引用(類似於方法引用),可以構造出具體類型的數組。
2、stream2collection
1 List<String> strList = strStream.collect(Collectors.toList());//返回List 2 Set<String> strSet = strStream.collect(Collectors.toSet());//返回set 3 ArrayList<String> strArrayList = strStream.collect(Collectors.toCollection(ArrayList::new));//收集到指定的List集合,例如收集到ArrayList
說明:
通過構造器引用,可以構造出具體類型的集合。
3、將stream中的元素拼接起來(joining()、joining(","))
1 Stream<String> strStream = Stream.of("java","c++","c","python"); 2 String str = strStream.collect(Collectors.joining());//將所有字符串拼接起來,結果:javac++cpython 3 System.out.println(str); 4 5 String str2 = strStream.collect(Collectors.joining(","));//將所有字符串拼接起來,中間用","隔開,結果:java,c++,c,python 6 System.out.println(str2);
4、stream2map(toMap、toConcurrentMap)
1 Stream<String> strStream = Stream.of("java","c++","c","python"); 2 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), (x)->0)); 3 //Function.identity()-->返回strStream中的元素,toMap方法的我兩個參數都是Function接口型的,所以第二個參數即使只放0,也不能直接寫作0,可以使用如上的方式進行操作 4 5 for(String key : map1.keySet()){ 6 System.out.println("key:"+key+"->"+"value:"+map1.get(key)); 7 } 8 //結果 9 /* 10 key:python->value:0 11 key:c++->value:0 12 key:c->value:0 13 key:java->value:0 14 */
說明:
如果key重復的話,這時就會出現問題"duplicate key",采用如下方式解決(增加第三個參數):
1 Stream<String> strStream = Stream.of("java","c++","c","python","java"); 2 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key 3 (x)->0, //value 4 (existingValue, newValue) -> existingValue));//如果key重復,取舊值
需要指定返回map的具體類型(增加第四個參數)。
1 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key 2 (x)->0, //value 3 (existingValue, newValue) -> existingValue,//如果key重復,取舊值 4 TreeMap::new));//返回TreeMap
注意:每一個toMap就會對應一個相應的toConcurrentMap
三、filter(Predicate p)
注意:是選擇而非過濾。
1 Stream<String> streamSelf = Stream.of("python","basic","php"); 2 streamSelf.filter(str->str.startsWith("p")).forEach(System.out::println);
注意:
更好的寫法可能是下邊這種:
1 Predicate<String> startCondition = str->str.startsWith("p"); 2 streamSelf.filter(startCondition).forEach(System.out::println);
說明:將條件(通常是lambda表達式)抽取出來。這種方式在多個條件的情況下比較清晰。
注意:函數式接口 = lambda表達式 (即lambda表達式只能返回為函數式接口)
四、map(Function mapper)
作用:對流中的每一個元素進行操作。
1 Stream<String> streamSelf = Stream.of("python","basic","php"); 2 streamSelf.map(String::toUpperCase).forEach(System.out::println);
說明:將流內的每一個String全部轉換為了大寫。
五、reduce
作用:對stream中的每一個元素做聚合操作。
1 Stream<Integer> reduceStream = Stream.of(1,2,3,4,5); 2 Optional<Integer> sumOption = reduceStream.reduce((x,y)->x+y);//計算1+2+3+4+5,即對元素中的元素進行聚合計算,而map是對元素中的每一個元素分別計算(注意:如果stream為null的話,就會產生無效的結果,需要使用Optional接收) 3 //Optional<Integer> sumOption = reduceStream.reduce(Integer::sum);//計算1+2+3+4+5,即對元素中的元素進行聚合計算,而map是對元素中的每一個元素分別計算 4 5 Integer result = reduceStream.reduce(0, Integer::sum);//0為標識值,即計算:0+1+2+。。+5,如果整個stream為null,就返回標識值。 6 System.out.println(result);
注意:以上是reduce的簡單形式,即內聯函數是(T,T)->T,即返回值和參數類型是一樣的,返回值和參數類型不同的場景需要自己編寫函數(用的較少)
六、Optional
兩種用法:
1 Stream<String> optionalStream = Stream.of("java","python","basic"); 2 Optional<String> optionValue = optionalStream.filter(str->str.startsWith("p")).findFirst(); 3 optionValue.ifPresent(str->System.out.println(str));//if optionalValue為true,即str存在,則輸出str,當然也可以使用如下 4 String str = optionValue.orElse("xxx");//如果optionValue為false,即不存在以p開頭的字符串時,使用"xxx"來替代 5 System.out.println(str);
七、limit skip contact
1、limit(long size)
作用:截取stream的前size個元素。
1 Stream<String> streamSelf = Stream.of("python","basic","php"); 2 streamSelf.limit(2).forEach(System.out::println);//截取前兩個
2、skip(long size)
作用:跳過stream的錢size個元素
1 Stream<String> streamSelf = Stream.of("python","basic","php"); 2 streamSelf.skip(2).forEach(System.out::println);//跳過前兩個
3、contact(Stream<T>,Stream<T>)
作用:拼接兩個stream
1 Stream<String> streamSelf = Stream.of("python","basic","php"); 2 Stream<String> streamSelf2 = Stream.of("python2","basic2","php2"); 3 Stream.concat(streamSelf, streamSelf2).forEach(System.out::println);
八、聚合函數 count max min findFirst findAny anyMatch allMatch noneMatch
1 Stream<String> streamSelf = Stream.of("python","basic","php","b"); 2 System.out.println(streamSelf.count());//計算流中的元素個數 3 Optional<String> largest = streamSelf.max(String::compareToIgnoreCase);//尋找最大值 4 if(largest.isPresent()){ 5 System.out.println(largest.get()); 6 }
說明:min函數也一樣。
注意:Optional的使用,上邊的是最差的一種形式,見"六"。
1 Optional<String> firstMatch = streamSelf.filter(str->str.startsWith("b")).findFirst();//尋找第一個符合條件的元素 2 firstMatch.ifPresent(System.out::println);//這是Optional的第一種用法 3 4 Optional<String> anyMatch = streamSelf.parallel().filter(str->str.startsWith("b")).findAny();//返回集合中符合條件的任意一個元素,對於並行處理非常好(因為多個線程只要有一個線程找到了,整個計算就會結束) 5 if(anyMatch.isPresent()){ 6 System.out.println(anyMatch.get());//這裡的結果可能是b,有可能是basic 7 } 8 9 boolean isAnyMatch = streamSelf.parallel().anyMatch(str->str.startsWith("c"));//集合中是否有一個滿足條件 10 System.out.println(isAnyMatch); 11 12 Stream<String> streamSelf3 = Stream.of("basic","b"); 13 boolean isAllMatch = streamSelf3.parallel().allMatch(str->str.startsWith("b"));//集合中是否所有元素都滿足條件 14 System.out.println(isAllMatch); 15 16 boolean isAllNotMatch = streamSelf.parallel().noneMatch(str->str.startsWith("p"));//集合中是否沒有一個元素滿足條件 17 System.out.println(isAllNotMatch);
注意:
八、