1.什麼是Stream
Stream Api對集合數據進行操作,就類似於使用sql執行的數據庫查詢
Stream是數據渠道,用於操作數據源(集合、數組等)所生成的元素序列.
集合講的是數據,Stream講的是計算
注意:
- Stream自己不會存儲元素
- Stream不會改變源對象.相反,他會返回一個持有結果的新Stream
- Stream操作是延遲執行的,意味着他們會等到需要結果的時候才執行
1.1 Stream的操作三步驟
1.創建Stream
一個數據源(如:集合、數組),獲取一個流2.中間操作
一箇中間操作鏈,對數據源的數據進行處理3.終止操作
一旦執行了終止操作,就執行中間操作鏈
,併產生結果,之後,不會再被使用
2.Stream實例化
2.1 通過集合
- Stream<E> stream(): 返回一個順序流
- Stream<E> parallelStream(): 返回一個並行流
public void test() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小張", 32));
list.add(new Person("小王", 12));
// default Stream<E> Stream() 返回一個順序流
Stream<Person> stream = list.stream();
// default Stream<E> parallelStream() 返回一個並行流
Stream<Person> parallelStream = list.parallelStream();
}
2.2 通過數組
@Test
public void test2() {
int[] arr = {1, 2, 3, 4, 5, 6};
// 調用Arrays類的Stream<T> stream(T[] array) 返回一個流
IntStream stream = Arrays.stream(arr);
Person p1 = new Person("小張", 32);
Person p2 = new Person("小王", 12);
Person[] personArr = new Person[]{p1, p2};
Stream<Person> stream1 = Arrays.stream(personArr);
}
2.3 通過Stream類的靜態方法
@Test
public void test3() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Stream<Long> longStream = Stream.of(1L, 2L, 3L, 4L, 5L);
Stream<Double> doubleStream = Stream.of(1.0, 2.0, 3.0, 4.0, 5.0);
Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");
Stream<Person> personStream = Stream.of(new Person("小張", 32), new Person("小王", 12));
}
2.4 創建無限流
- Stream<T> iterate(final T seed, final UnaryOperator<T> f)
final T seed:初始值
final UnaryOperator<T> f:函數式接口,參數和返回值都是一個類型的
// 遍歷從0開始的前10個偶數
@Test
public void test4() {
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
}
- Stream<T> generate(Supplier<T> s)
Supplier<T> s:無參數,返回類型爲任意類型的函數式接口
// 生成
Stream.generate(Math::random).limit(10).forEach(System.out::println);
3.Stream的中間操作
多個中間操作可以連接形成一個流水線
,除非流水線上觸發終止操作,否則中間操作不會執行任何處理
!而在終止操作時,一次性全部處理,稱爲"惰性求值"
3.1 篩選和切片
- filter(Predicate p)
接收lambda,從流中排除某些元素 - distinct()
篩選,通過流所生成的元素 hashCode()和equals去除重複元素 - limit(long maxSize)
截斷流,使其元素不超過給定數量 - skip(long n)
跳過元素,返回一個扔掉了前n個元素的流,若流中元素不足n個,則返回一個空流,與limit(n)互補
@Test
public void test4() {
getStream().filter(t -> t.age >20).forEach(System.out::println);
getStream().limit(3).forEach(System.out::println);
getStream().skip(2).forEach(System.out::println);
// 需要重寫Person類的hashCode()和equals()方法
getStream().distinct().forEach(System.out::println);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小張", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
3.2 映射
- map(Function<? super T, ? extends R> mapper)
接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射爲一個新的元素 - <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
接收一個函數作爲參數,將流中每個值轉換成另一個流,然後將所有流連成一個流
@Test
public void test5() {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
// 獲取年齡大於20歲的人的姓名
getStream().filter(t -> t.age > 20).map(t -> t.name).forEach(System.out::println);
// 使用map
Stream<Stream<Character>> streamStream = list.stream().map(StreamApi::fromStringToStream);
streamStream.forEach(t -> {
t.forEach(System.out::println);
System.out.println("---");
});
// 使用flatMap
Stream<Character> characterStream = list.stream().flatMap(StreamApi::fromStringToStream);
characterStream.forEach(System.out::println);
}
public static Stream<Character> fromStringToStream(String str) {
ArrayList<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小張", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
3.3 排序
@Test
public void test6() {
List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98);
// 自然排序
list.stream().sorted().forEach(System.out::println);
// 使用定製排序
getStream().sorted((o1, o2) -> o2.age - o1.age).forEach(System.out::println);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小張", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
4.Stream的終止操作
4.1 匹配和查找
- boolean allMatch(Predicate<? super T> predicate): 檢查是否匹配所有元素
- boolean anyMatch(Predicate<? super T> predicate): 檢查是否至少匹配一個元素
- boolean noneMatch(Predicate<? super T> predicate): 檢查是否沒有匹配的元素
- Optional<T> findFirst(): 返回第一個元素
- Optional<T> findAny(): 返回當前流中任意元素(在parallelStream下使用)
- long count(): 返回流中元素的總個數
- Optional<T> max(Comparator<? super T> comparator): 返回流中最大值
- Optional<T> min(Comparator<? super T> comparator): 返回流中最小值
- void forEach(Consumer<? super T> action): 內部迭代
@Test
public void test6() {
// 是否所有人的年齡都大於18歲
boolean b1 = getStream().allMatch(t -> t.age > 18);
System.out.println(b1);
// 是否存在大於18歲的人
boolean b2 = getStream().anyMatch(t -> t.age > 18);
System.out.println(b2);
// 是否所有人的年齡都不大於18
boolean b3 = getStream().noneMatch(t -> t.age > 18);
System.out.println(b3);
// 返回第一個元素
Optional<Person> first = getStream().findFirst();
System.out.println(first);
// 返回當前流中任意元素(在parallelStream下使用)
Optional<Person> any = getStream().findAny();
System.out.println(any);
// 返回流中元素的總個數
long count = getStream().count();
System.out.println(count);
// 返回流中最大值
Optional<Person> max = getStream().max((o1, o2) -> Integer.compare(o1.age, o2.age));
System.out.println(max);
// 返回流中最小值
Optional<Person> min = getStream().min((o1, o2) -> Integer.compare(o1.age, o2.age));
System.out.println(min);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小張", 32));
list.add(new Person("小王", 12));
return list.stream();
}
4.2 歸約
- T reduce(T identity, BinaryOperator<T> accumulator); 可以將流中元素反覆結合起來,得到一個值
- Optiona\l reduce(BinaryOperator<T> accumulator); 可以將流中元素反覆結合起來,得到一個值
public void test6() {
// 計算1~10的自然數的總和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
// 計算年齡的總和
Stream<Integer> ageStream = getStream().map(t -> t.age);
Optional<Integer> ageSum = ageStream.reduce(Integer::sum);
System.out.println(ageSum);
}
4.3 收集
- <R, A> R collect(Collector<? super T, A, R> collector);
// 將年紀大於20歲的人,存入一個集合中
List<Person> collect = getStream().filter(t -> t.age > 20).collect(Collectors.toList());
System.out.println(collect);