一、概述
Stream 關注的是對數據的運算,與CPU打交道;集合關注的是數據的存儲,與內存打交道
- Stream自己不會存儲數據
- Stream不會改變源數據,相反,他們會返回一個持有結果的新Stream
- Stream操作是延遲執行的,這意味着他們會等到需要結果的時候才執行
步驟:
- 創建Stream,一個數據源(如:集合,數組),獲取一個流
- 中間操作,一箇中間操作鏈,對數據源的數據進行處理
- 終止操作,一旦執行終止操作,就執行中間操作鏈,併產生結果,之後,不會再被使用
二、創建Strem
1.通過集合
Java8中的Collection接口有stream,paralleStream方法:
- default Stream<E> stream() 返回一個順序流
- default Stream<E> paralleStream() 返回一個並行流
@Test
public void test11() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Stream<Integer> stream = list.stream();
Stream<Integer> integerStream = list.parallelStream();
}
2.通過數組
Arrays有靜態方法stream()可以獲取數組流:
- public static IntStream stream(int[] array)
- public static LongStream stream(long[] array)
- public static DoubleStream stream(double[] array)
@Test
public void test12() {
int[] arr = new int[] {1, 2, 3};
IntStream intStream = Arrays.stream(arr);
}
3.通過Stream的of()
Stream類有靜態方法of()可以獲取一個流
- public static<T> Stream<T> of(T... values)
@Test
public void test13() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
}
4.創建無限流
可以使用靜態方法Stream.iterate()和Stream.generate()創建無限流
- public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- public static<T> Stream<T> generate(Supplier<T> s)
@Test
public void test14() {
Stream<Integer> iterate = Stream.iterate(0, t -> t + 2);
Stream<Double> generate = Stream.generate(Math::random);
}
三、Stream的中間操作
1.篩選與切片
- filter(Predicate p) 接受Lambda,從流中篩選某些元素
- distinct() 通過流生成元素的hashCode()和equals()去除重複元素
- limit(long maxSize) 截斷流,使其元素不超過給定數量
- skip(long n) 跳過元素,返回一個扔掉了前n個元素的流,若流中元素不足n個,則返回一個空流,與limit(n)互補
@Test
public void test21() {
List<String> list = Arrays.asList("C", "A", "A", "B");
// 1.filter
Stream<String> stream = list.stream();
stream.filter((s) -> s.equals("A")).forEach(System.out::print);
System.out.println();
// 2.distinct
stream = list.stream();
stream.distinct().forEach(System.out::print);
System.out.println();
// 3.limit
stream = list.stream();
stream.limit(2).forEach(System.out:: print);
System.out.println();
// 4.skip
stream = list.stream();
stream.skip(2).forEach(System.out::print);
System.out.println();
}
結果:
2.映射
- map(Function f) 接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素
- mapToDouble(ToDoubleFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的DoubleStream
- mapToInt(ToIntFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的DoubleStream
- mapToLong(ToLongFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的LongStream
- flatMap(Function f) 接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流
@Test
public void test22() {
List<String> list = Arrays.asList("C", "A", "A", "B");
list.stream().map(str -> str.toLowerCase()).forEach(System.out::print);
}
結果:
3.排序
- sorted() 產生一個新流,其中按自然順序排序
- sorted(Comparator com) 產生一個新流,其中按比較器順序排序
@Test
public void test23() {
List<String> list = Arrays.asList("C", "A", "A", "B");
list.stream().sorted().forEach(System.out::print);
}
結果:
四、Stream的終止操作
1.匹配與查找
- allMatch(Predicate p) 檢查是否匹配所有元素
- anyMatch(Predicate p) 檢查是否至少匹配一個元素
- noneMatch(Predicate p) 檢查是否沒有匹配所有元素
- findFirst() 返回第一個元素
- findAny() 返回當前流中的任意元素
- count() 返回流中元素總數
- max(Comparator c) 返回流中最大值
- min(Comparator c) 返回流中最小值
- forEach(Consumer c) 內部迭代(使用Collection接口需要用戶去做迭代,稱爲外部迭代,相反,Stream API使用內部迭代--它幫你把迭代做了)
@Test
public void test31() {
List<String> list = Arrays.asList("C", "A", "A", "B");
boolean allMatch = list.stream().allMatch(e -> e.equals("B"));
System.out.println(allMatch);
boolean anyMatch = list.stream().anyMatch(e -> e.equals("B"));
System.out.println(anyMatch);
}
結果:
2.歸約
- reduce(T iden, BinaryOperator b) 可以將流中元素反覆結合起來,得到一個值,返回T
- reduce(BinaryOperator b) 可以將流中元素反覆結合起來,得到一個值,返回Optional<T>
@Test
public void test32() {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println(sum);
}
結果:
3.收集
Colletor接口中方法的實現決定了如何對流執行收集的操作(如收集到List,Set,Map)
Collectors實用類提供了很多靜態方法,可以方便地創建常見收集器實例
- collect(Collector c) 將流轉換爲其他形式,接收一個Collector接口的實現,用於給Stream中元素做彙總的方法
@Test
public void test33() {
List<String> list = Arrays.asList("C", "A", "A", "B");
List<String> resList = list.stream().filter(e -> e.equals("A")).collect(Collectors.toList());
System.out.println(resList);
}
結果: