爲什麼需要使用Stream
Stream 的操作流程
- 獲取一個數據源(source)
- 中間數據操作
執行中間操作,每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(可以有多次轉換),這就允許對其操作可以像鏈條一樣排列,變成一個管道 - 終止操作,獲得想要的結果
如下圖所示:
Intermediate(中間數據操作):
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal(終止操作):
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting(短路操作):
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
獲取一個數據源(source)
- Collection 和數組Arrays中的靜態方法
Collection.stream();Collection.parallelStream()
Arrays.stream(T array) or Stream.of()
例如:
Stream<String> listStream = Arrays.asList("aa","bb","cc").stream();
String[] stringArray = {"aa","bb","cc"};
Stream<String> arrayStream = Arrays.stream(stringArray);
- 通過Stream類中的一些靜態方法獲取流
例如 Stream.of();Stream.iterate();Stream.generate()
Stream<String> stream = Stream.of("aa","bb","cc");
Stream<Integer> stream1 = Stream.iterate(2, (x) -> x * 2);
Stream<Double> stream2 = Stream.generate(() -> Math.random());
- 其它一些類,可以獲取stream對象
java.nio.file.Files.walk()
Random.ints()
BitSet.stream()
Pattern.splitAsStream(java.lang.CharSequence)
JarFile.stream()
ava.io.BufferedReader.lines()
中間數據操作
即對數據的流進行一些需要的操作,在終止操作執行之前,中間操作可以不斷執行。
如圖:
中間操作主要用到strem類提供的一些可以返回Stream流的靜態方法,主要示例一些常用的方法,其他可參考在線中文JDK1.8 http://www.matools.com/api/java8
filter(Predicate<? super T> predicate)
顧名思義,過濾輸入流中的一些元素,只輸出符合條件的一些元素,需要給定篩選條件(Predicate<? super T> predicate)
舉例說明:
Stream<String> listStream = Arrays.asList("aa","bb","cc").stream();
Stream<String> handledStream = listStream.filter(a -> "aa".equals(a));
System.err.println("filter after:" + handledStream.collect(Collectors.toList()));
輸出結果爲:
從結果中可以看出來,原有數組中[“aa”,“bb”,“cc”],經過過濾條件 “aa”.equals(a) 的篩選以後,新輸出的數組,只剩下了符合條件的[“aa”]。
此處可能會產生兩個疑問:
- 此時如果執行
System.err.println("before:" + listStream.collect(Collectors.toList()));
會報錯,爲什麼呢?
流只能被讀一遍,詳細見後文 handledStream.collect(Collectors.toList())
是什麼意思呢?
將流轉換爲List,方便輸出查看結果,詳細見後文
按照上面的思路,把Stream中的一些靜態方法都執行一遍,看每個靜態方法都有什麼作用。
distinct()
返回由該流的不同元素(根據 Object.equals(Object) )組成的流。即去重的意思
@Test
public void streamDistinctTest() {
Stream<String> listStream = Arrays.asList("aa","aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.distinct();
System.err.println("distinct after:" + handledStream.collect(Collectors.toList()));
}
結果如下:
從結果中看,原數組爲[“aa”,“aa”, “bb”, “cc”, “eee”, “cc”],distinct之後,重複的"aa","cc"被去除掉了。
上文中的 “根據 Object.equals(Object)” 又是什麼意思呢,即如果傳入是一個Object對象,判斷是否重複的辦法是調用equels方法去重,如果需要實現自己的去重規則,需要重寫對象中的equels方法。
limit(long maxSize)
返回由此流的元素組成的流,截短長度不能超過 maxSize。即截取maxSize長度的數據。
@Test
public void streamLimitTest() {
Stream<String> listStream = Arrays.asList("aa","aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.limit(3);
System.err.println("limit after:" + handledStream.collect(Collectors.toList()));
}
結果如下:
skip(long n)
丟棄前n個元素,只保留後面的元素
@Test
public void streamSkipTest() {
Stream<String> listStream = Arrays.asList("aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.skip(2);
System.err.println("skip after:" + handledStream.collect(Collectors.toList()));
}
結果如下:
從結果中可以看出來,skip跳過了前兩個元素,只返回了後三個元素
sorted()
返回由此流的元素組成的流,根據自然順序排序。
@Test
public void streamSortTest() {
Stream<String> listStream = Arrays.asList("hh", "gg", "ee", "dd", "cc").stream();
Stream<String> handledStream = listStream.sorted();
System.err.println("sorted after:" + handledStream.collect(Collectors.toList()));
}
結果如下:
從結果中可以看到,對原數組[“hh”, “gg”, “ee”, “dd”, “cc”],進行了一個字符串的排序
map
map()方法爲流中的每個輸入值生成一個輸出值。
因此,如果流中有n個元素,則map()操作將生成n個輸出元素的流。
@Test
public void streamMapTest() {
List<String> listOfStrings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> listOfIntegers = listOfStrings.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
System.err.println(listOfIntegers);
}
flatMap
flatMap()是兩步過程,即map()+ Flattening。
它有助於將Collection <Collection >轉換爲Collection 。
@Test
public void streamFlatMapTest() {
List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
List<Integer> list3 = Arrays.asList(7,8,9);
List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
List<Integer> listOfAllIntegers = listOfLists.stream()
.flatMap(x -> x.stream())
.collect(Collectors.toList());
System.err.println(listOfAllIntegers);
}
終止操作
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator、collect