一逗鸣、什么是 Stream?
Stream 是 Java8 中處理集合的關(guān)鍵抽象概念帘饶,它可以指定你希望對集合進行的操作,可以執(zhí)行非常復雜的查找群扶、過濾和映射數(shù)據(jù)等操作及刻。
使用 Stream API 對集合數(shù)據(jù)進行操作,就類似于使用 SQL 執(zhí)行的數(shù)據(jù)庫查詢竞阐。也可以使用 Stream API 來并行執(zhí)行操作缴饭。簡而言之,Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式骆莹。
二颗搂、Stream 的特點
- stream 自己不會保存數(shù)據(jù)。
- 不會改變數(shù)據(jù)源幕垦,相反丢氢,他們會返回一個持有結(jié)構(gòu)的新的 Stream。
- Stream 操作是延遲執(zhí)行的先改,因此疚察,它會等到需要結(jié)果時才執(zhí)行。
三仇奶、Stream 的三個操作步驟
產(chǎn)生 Stream
① 通過 Collections 系列集合提供的 stream()方法或 parallelStream()獲取
② 通過 Arrays 中的靜態(tài)方法獲取
③ 通過 Stream 類中的靜態(tài)方法 of()獲取
④ 創(chuàng)建無限流
⑤ ...中間操作
(1)篩選與切片:
??① Stream<T> filter(Predicate predicate); // 過濾(返回值 boolean)
??② Stream<T> limit(long maxSize); // 限制
??③ Stream<T> skip(long n); // 跳過
??④ Stream<T> distinct(); // 去重(比較 hash 值)
(2)映射
??① Stream<R> map(Function mapper); // 參數(shù) lambda 表達式(有返回值)
??② Stream<R> flatMap(Function mapper); // 參數(shù) lambda 表達式(有返回值)
(3)排序
??① Stream<T> sorted() // 自然排序 Comparable
??② Stream<T> sorted(Comparator comparator); // 定制排序
(4)消費(與 map() 相似)
??① Stream<T> peek(Consumer action); // 參數(shù) lambda 表達式(無返回值)終止操作(終端操作)
(1)查找與匹配
??allMatch:檢查是否匹配所有元素
??noneMatch:檢查是否沒匹配所有元素
??anyMatch:檢查是否至少有一個元素匹配
??findFirst:返回流中第一個元素
??findAny:返回流中的任意元素
??count:返回流中元素的總個數(shù)
??max:返回流中元素最大值
??min:返回流中元素最小值
(2)歸約與收集
??① Optional<T> reduce(BinaryOperator<T> accumulator)
??② R collect(Collector collector);
四貌嫡、Stream 演示
以下為全部代碼,可直接運行
Person.java
package com.wl.model;
/**
* @author WL
* @date : 2021年6月3日 08:27:19
*/
public class Person implements Comparable<Person> {
private String name;
private Integer age;
private String gender;
public Person() {
}
public Person(String name, Integer age, String gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
@Override
public int compareTo(Person person) {
return person.getAge() - this.age;
}
}
StreamDemo.java
package com.wl.stream;
import com.wl.model.Person;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author WL
* @date : 2021年6月3日 08:27:19
*/
public class StreamDemo {
public static Person person1 = new Person("Tom", 20, "男");
public static Person person2 = new Person("Scott", 21, "女");
public static Person person3 = new Person("John", 22, "男");
public static Person person4 = new Person("Bob", 23, "女");
public static List<Person> list = Arrays.asList(person1, person2, person3, person4, person4);
public static void main(String[] args) {
System.out.println("請輸入要要演示的方法序號:");
System.out.println("1.創(chuàng)建 Stream");
System.out.println("2.中間操作--篩選與切片");
System.out.println("3.中間操作--映射");
System.out.println("4.中間操作--映射");
System.out.println("5.中間操作--排序");
System.out.println("6.查找與匹配");
System.out.println("7.歸約與收集");
System.out.println("8.退出");
System.out.println("請輸入數(shù)字:(例:6)");
while (true) {
int num = new Scanner(System.in).nextInt();
if (num == 1) {
test1();
} else if (num == 2) {
test2();
} else if (num == 3) {
test3();
} else if (num == 4) {
test4();
} else if (num == 5) {
test5();
} else if (num == 6) {
test6();
} else if (num == 7) {
test7();
} else if (num == 8) {
break;
} else {
System.err.println("您輸入的數(shù)字不正確,請重新輸入:");
}
}
}
/**
* 創(chuàng)建 Stream
*/
public static void test1() {
// 1. 通過 Collections 系列集合提供的 stream()方法或 parallelStream()獲取
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
list.forEach(System.out::println);
// 2. 通過 Arrays 中的靜態(tài)方法獲取
String[] strArr = {"aaa", "bbb", "ccc"};
Stream<String> stream2 = Arrays.stream(strArr);
// 3. 通過 Stream 類中的靜態(tài)方法 of()獲取
Stream<String> stream3 = Stream.of("111", "222", "333");
// 4. 創(chuàng)建無限流
// 迭代
Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
stream4.limit(20).forEach(System.out::println);
// 生成
Stream.generate(Math::random).limit(8).forEach(System.out::println);
}
/**
* 中間操作--篩選與切片
*/
public static void test2() {
// distinct()比較 hash 值
Stream<Person> stream = list.stream().filter(person -> person.getAge() > 20).distinct();
// 終止,無終止岛抄,中間操作不執(zhí)行
stream.forEach(System.out::println);
}
/**
* 中間操作--映射
*/
public static void test3() {
System.out.println("---------------------map----------------------------");
Stream<Person> stream1 = list.stream().map(person -> {
person.setAge(person.getAge() + 10);
return person;
});
stream1.forEach(System.out::println);
System.out.println("----------------------map----------------------------");
Stream<String> strs = list.stream().map(Person::getName);
strs.forEach(System.out::println);
System.out.println("----------------------flatMap----------------------------");
List<String> strList = Arrays.asList("a,b,c", "d,e", "f,g,h,i");
// 把 {{a,b,c},{d,e},{f,g,h,i}} 流轉(zhuǎn)化為 {a,b,c,d,e,f,g,h,i}
Stream<String> stream2 = strList.stream().flatMap(s -> {
String[] strArr = s.split(",");
return Arrays.stream(strArr);
});
stream2.forEach(System.out::println);
}
/**
* 中間操作--排序
*/
public static void test4() {
System.out.println("----------------------sorted Comparable----------------------------");
// 使用 sorted()别惦,Person 類需實現(xiàn) Comparable 接口,重寫 compareTo()方法
/*
* @Override
* public int compareTo(Person person) {
* return person.getAge() - this.age;
* }
*/
list.stream().sorted().forEach(System.out::println);
System.out.println("----------------------sorted Comparator----------------------------");
System.out.println("----------------------age從大到小----------------------------");
list.stream().sorted((p1, p2) -> p2.getAge() - p1.getAge()).forEach(System.out::println);
System.out.println("----------------------age從小到大----------------------------");
list.stream().sorted(Comparator.comparingInt(Person::getAge)).forEach(System.out::println);
}
/**
* 中間操作--排序
*/
public static void test5() {
list.stream().peek(p -> p.setAge(25)).forEach(System.out::println);
}
/**
* 查找與匹配
*/
public static void test6() {
System.out.println(list.stream().allMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().noneMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().anyMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().findFirst().get());
System.out.println(list.stream().findAny().get());
System.out.println(list.stream().count());
System.out.println(list.stream().max(Comparator.comparingInt(Person::getAge)).get());
System.out.println(list.stream().min(Comparator.comparingInt(Person::getAge)).get());
}
/**
* 歸約與收集
*/
public static void test7() {
Integer ageSum = list.stream().map(Person::getAge).reduce(Integer::sum).get();
System.out.println("年齡總和:" + ageSum);
Set<String> nameSet = list.stream().map(Person::getName).collect(Collectors.toSet());
System.out.println(nameSet);
HashSet<String> nameHashSet = list.stream().map(Person::getName).collect(Collectors.toCollection(HashSet::new));
System.out.println(nameHashSet);
Double avgAge = list.stream().collect(Collectors.averagingDouble(Person::getAge));
System.out.println("平均年齡:" + avgAge);
Integer a = list.stream().mapToInt(Person::getAge).sum();
System.err.println(a);
}
}