在具體的介紹之前,先總結一波常用的寫法,有基礎的可以直接拿來用,沒有基礎的可以先跳過,看完下面的基礎再回來看

List<User> userList = new ArrayList<>(); userList.addAll(Arrays.asList( new User(1, 11, "張三"), new User(1, 11, "張三"), new User(2, 22, "李四"), new User(1, 33, "王五"), new User(2, 44, "趙六"), new User(2, 44, "趙六"))); //----------------------------------------------中間操作---------------------------------------------- //【filter】從列表中篩選出性別為女的數據 List<User> filterUsage = userList.stream().filter(s->s.getSex() == 2).collect(Collectors.toList()); //結果:[User(sex=2, age=22, name=李四), User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)] System.out.println(filterUsage); //【distinct】從列表中去重 List<User> distinctUsage = userList.stream().distinct().collect(Collectors.toList()); //結果:[User(sex=1, age=11, name=張三), User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)] System.out.println(distinctUsage); //【sorted】按照年齡字段從大到小重新排序 (從小到大就是s1.getAge()-s2.getAge()) List<User> sortedUsage = userList.stream().sorted((s1,s2)->s2.getAge()-s1.getAge()).collect(Collectors.toList()); //結果:[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六), User(sex=1, age=33, name=王五), User(sex=2, age=22, name=李四), User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)] System.out.println(sortedUsage); //【limit】獲取前兩條數據 List<User> limitUsage = userList.stream().limit(2).collect(Collectors.toList()); //結果:[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)] System.out.println(limitUsage); //【skip】跳過前兩條,之后獲取前三條數據 List<User> skipUsage = userList.stream().skip(2).limit(3).collect(Collectors.toList()); //結果:[User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)] System.out.println(skipUsage); //【map】獲取所有人的姓名 List<String> mapUsage = userList.stream().map(User::getName).collect(Collectors.toList()); //結果:[張三, 張三, 李四, 王五, 趙六, 趙六] System.out.println(mapUsage); //【flatMap】 //【Collectors工具類一些常用方法】 //【groupingBy】分組 // 將集合中的數據按照姓名分組 Map<String, List<User>> groupingByUsage = userList.stream().collect(Collectors.groupingBy(s -> s.getName())); //結果:{李四=[User(sex=2, age=22, name=李四)], 張三=[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)], // 王五=[User(sex=1, age=33, name=王五)], 趙六=[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)]} System.out.println(groupingByUsage); // 將集合中的數據按照姓名+性別分組 Map<String, List<User>> groupingByUsage2 = userList.stream().collect(Collectors.groupingBy(s -> s.getName() + "#" + s.getSex())); //結果:{張三#1=[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)], 李四#2=[User(sex=2, age=22, name=李四)], // 趙六#2=[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)], 王五#1=[User(sex=1, age=33, name=王五)]} System.out.println(groupingByUsage2); //【maxBy】獲取集合中年齡最大的對象信息 User maxByUsage = userList.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get(); //結果:User(sex=2, age=44, name=趙六) System.out.println(maxByUsage); //【minBy】獲取集合中年齡最小的對象信息 User minByUsage = userList.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get(); //結果:User(sex=1, age=11, name=張三) System.out.println(minByUsage); //【joining】拼接集合中所有的用戶名稱---直接拼接 String joiningUsage = userList.stream().map(User::getName).collect(Collectors.joining()); //結果:張三張三李四王五趙六趙六 System.out.println(joiningUsage); //拼接中間加上逗號 String joiningUsage2 = userList.stream().map(User::getName).collect(Collectors.joining(",")); //結果:張三,張三,李四,王五,趙六,趙六 System.out.println(joiningUsage2); //拼接中間加上逗號,兩邊加上前后綴 String joiningUsage3 = userList.stream().map(User::getName).collect(Collectors.joining(",","[","]")); //結果:[張三,張三,李四,王五,趙六,趙六] System.out.println(joiningUsage3); //【counting】獲取集合中對象的數量 Long countingUsage = userList.stream().collect(Collectors.counting()); //結果:6 System.out.println(countingUsage); //【summingInt】獲取集合中所有對象年齡的和 int summingIntUsage = userList.stream().collect(Collectors.summingInt(User::getAge)); //結果:165 System.out.println(summingIntUsage); //【averagingInt】獲取集合中所有對象年齡的平均值 Double averagingIntUsage = userList.stream().collect(Collectors.averagingInt(User::getAge)); //結果:27.5 System.out.println(averagingIntUsage); //【summarizingInt】獲取集合中所有對象的數量/和/最大值/最小值/平均值等信息 IntSummaryStatistics summarizingIntUsage = userList.stream().collect(Collectors.summarizingInt(User::getAge)); //結果:IntSummaryStatistics{count=6, sum=165, min=11, average=27.500000, max=44} System.out.println(summarizingIntUsage); //----------------------------------------------最終操作---------------------------------------------- //【collect】 //這里不做演示,上面的所有例子中都有用到 //【reduce】將集合中的所有性別字段的值按照相加的規則求乘積 Integer reduceUsage = userList.stream().map(User::getSex).reduce((s1, s2) -> s1 * s2).get(); //結果:8 System.out.println(reduceUsage); //【count】求集合中對象的數量 long countUsage = userList.stream().count(); //結果:6 System.out.println(countUsage); //【forEach】遍歷出所有的對象的名稱 Consumer<String> action = System.out::println; //結果:張三 張三 李四 王五 趙六 趙六 userList.stream().map(User::getName).forEach(action); //【max&min】獲取集合中所有對象中年齡的最大值和最小值 Integer maxUsage = userList.stream().map(User::getAge).max(Integer::compareTo).get(); //結果:44 System.out.println(maxUsage); Integer minUsage = userList.stream().map(User::getAge).min(Integer::compareTo).get(); //結果:11 System.out.println(minUsage); //【Matching -> allMatch、anyMatch、noneMatch】 //allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true boolean allMatchUsage = userList.stream().map(User::getAge).allMatch(e -> e >= 44); //結果:false System.out.println(allMatchUsage); //anyMatch:只要流中有任意的數據,滿足指定的規則,都會返回true boolean anyMatchUsage = userList.stream().map(User::getAge).anyMatch(e -> e <= 11); //結果:true System.out.println(anyMatchUsage); //noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true boolean noneMatchUsage = userList.stream().map(User::getAge).noneMatch(e -> e < 11); //結果:true System.out.println(noneMatchUsage); //【find--> findFirst、findAny】【parallelStream並行流、stream串行流】 //findFirst:從流中獲取開頭第一個元素 User user = userList.stream().findFirst().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user); User user2 = userList.parallelStream().findFirst().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user2); //findAny:單線程是獲取第一個元素,多線程可能不一樣 User user3 = userList.stream().findAny().get(); //結果:User(sex=1, age=11, name=張三) System.out.println(user3); User user4 = userList.parallelStream().findAny().get(); //結果:User(sex=1, age=33, name=王五) System.out.println(user4); //【IntStream+summaryStatistics】獲取int數組中的最大值 //1.准備一個int數組作為數據源 int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; //2.讀取數據到流中,獲取IntStream對象 IntStream intStream = Arrays.stream(array); //兩種方法:(不能一起用,因為是中間操作) //1. 直接通過IntStream來獲取 //System.out.println(intStream.max().getAsInt()); //2. 通過IntSummaryStatistics,里面包括最大/最小/平均/數量等方法 IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics(); //結果:9 System.out.println(intSummaryStatistics.getMax()); //----------------------------------------------其它操作---------------------------------------------- //【list轉數組1】 Integer[] ints = userList.stream().map(User::getAge).toArray(Integer[]::new); //【list轉數組2】 List<String> list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); String[] strings = list.toArray(new String[list.size()]); //【數組轉list】 String[] arrays = {"1", "2", "3"}; List<String> listStrings = Stream.of(arrays).collect(Collectors.toList()); //結果:[1, 2, 3] System.out.println(listStrings); //【修改集合中的對象屬性的值】 //原值:[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三), User(sex=2, age=22, name=李四), // User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)] System.out.println(userList); userList.forEach(s->{ s.setAge(100); s.setSex(100); }); //新值:[User(sex=100, age=100, name=張三), User(sex=100, age=100, name=張三),User(sex=100, age=100, name=李四), // User(sex=100, age=100, name=王五), User(sex=100, age=100, name=趙六), User(sex=100, age=100, name=趙六)] System.out.println(userList);
一、集合流的簡介
1. 集合的流式編程的簡介
Stream是JDK1.8之后出現的新特性,也是JDK1.8新特性中最值得學習的兩種新特性之一(另一個是lambda表達式)Stream是對集合操作的增強,流不是集合的元素,不是一種數據結構,不負責數據的存儲的。流更像是一個迭代器,可以單向的遍歷一個集合中的每一個元素,並且不可循環。
2. 為什么要使用集合的流式編程
有些時候,對集合中的元素進行操作的時候,需要使用到其他操作的結果。在這個過程中,集合的流式編程可以大幅度的簡化代碼的數量。將數據源中的數據,讀取到一個流中,可以對這個流中的數據進行操作(刪除、過濾、映射...)。每次的操作結果也是一個流對象,可以對這個流再進行其它的操作。
3. 使用流式編程的步驟
通常情況下,對集合中的數據使用流式編程,需要經過以下三步:
(1)獲取數據源,將數據源中的數據讀取到流中
(2)對流中的數據進行各種各樣的處理
(3)對流中的數據進行整合處理
在上述三個過程:
(1)過程2中,有若干方法,可以對流中的數據進行各種各樣的操作,並且返回流對象本身,這樣的操作,被稱為中間操作
(2)過程3中,有若干方法,可以對流中的數據進行各種處理,並關閉流,這樣的操作,被稱為最終操作
在中間操作和最終操作中,基本上所有的方法參數都是函數式接口,可以使用lambda表達式來實現。使用集合的流式編程,來簡化代碼量。
二、數據源的獲取
1. 數據源的簡介
數據源,顧名思義,就是流中的數據的來源,是集合的流式編程的第一步,將數據源中的數據讀取到流中,進行處理。注意:將數據讀取到流中進行處理的時候,與數據源中的數據沒有關系。也就是說,中間操作對流中的數據進行處理、過濾、映射、排序...是不會影響到數據源中的數據的。
2. 數據源的獲取
這個過程,其實是將一個容器中的數據,讀取到一個流中,因此無論什么容器作為數據源,讀取到流中的方法返回值一定是一個Stream。
public static void main(String[] args) throws Exception{ //將集合作為數據源,讀取集合中的數據到一個流中 collectionDataSource(); //將數組作為數據源,讀取數組中的數據到一個流中(使用引用數據類型) arrayDataSource(); //將數組作為數據源,讀取數組中的數據到一個流中(使用基本數據類型) } //將集合作為數據源,讀取集合中的數據到一個流中 public static void collectionDataSource(){ //1.實例化一個集合 List<Integer> list = new ArrayList<>(); //2.填充元素 Collections.addAll(list,0,1,2,3,4,5,6,7,8,9); //3.讀取集合中的數據,將其讀取到流中 //Stream<Integer> stream = list.stream();//同步流 Stream<Integer> integerStream = list.parallelStream();//並發流 //4.輸出stream System.out.println(integerStream);//java.util.stream.ReferencePipeline$Head@4554617c } //將數組作為數據源,讀取數組中的數據到一個流中 public static void arrayDataSource(){ //1.實例化一個數組 Integer[] array = new Integer[]{0,1,2,3,4,5,6,7,8,9}; //2.讀取數組中的數據到流中,得到一個流對象 Stream<Integer> stream = Arrays.stream(array); //3.輸出Stream System.out.println(stream); } //將數組作為數據源,讀取數組中的數據到一個流中 //集合中只能存引用數據類型,但是數組中不用 public static void arrayDataSource2(){ //1.實例化一個數組 int[] array = new int[]{0,1,2,3,4,5,6,7,8,9}; //2.讀取數組中的數據到流中,得到一個流對象 IntStream stream = Arrays.stream(array); //3.輸出Stream System.out.println(stream); }
三、最終操作
將流中的數據整合到一起,可以存入一個集合,也可以直接對流中的數據進行遍歷,數據統計...通過最終操作,需要掌握如何從流中提取出來我們想要的信息。
注意事項:最終操作,在執行結束之后,會關閉這個流,流中的所有數據都會被銷毀,如果使用一個已經關閉了的流,會出現異常。
最終操作包括:collect、reduce、count、forEach、max&min、Matching、find、IntStream等。
1. collect
將流中的數據收集到一起,對這些數據進行一些處理。最常見的處理,就是將流中的數據存入一個集合。collect方法的參數,是一個collector接口,而且這個接口並不是一個函數式接口,實現這個接口,可以自定義收集的規則。但是,絕大部分情況下,不需要自定義。
直接使用Collectors工具類提供的方法即可。

public class FinalOperation { public static void main(String[] args) { collectUsage(); } //最終操作:collect將流中的數據整合起來,最常見的處理是:讀取流中的數據,整合到一個容器中,得到一個集合。 public static void collectUsage(){ //1.讀取數據源 Stream<Integer> dataSource = getDataSource(); //2.流中的數據的聚合 //List<Integer> list = dataSource.collect(Collectors.toList()); //System.out.println(list);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] //Set<Integer> set = dataSource.collect(Collectors.toSet()); //System.out.println(set);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] //Map<String, Integer> map = dataSource.collect(Collectors.toMap(i -> i.toString(), i -> i));//i.toString作為鍵 i作為值 Map<String, Integer> map = dataSource.collect(Collectors.toMap(Object::toString, i -> i));//i.toString作為鍵 i作為值 System.out.println(map);//{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9} } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); } }
2. reduce
將流中的數據按照一定的規則聚合起來。將流的元素,逐一帶入這個方法中,進行運算。最終的運算結果,得到的其實是一個Optional類型,需要使用get()獲取到里面的數據

public class FinalOperation { public static void main(String[] args) { reduceUsage(); } public static void reduceUsage(){ //1.讀取數據源,得到流對象 Stream<Integer> dataSource = getDataSource(); //2.最終操作 (這里有兩個參數,實現了從0到9的和的求值 即p1=0 p2=1 和的結果為1作為p1 再跟p2=2相加,以此類推) Integer num = dataSource.reduce((p1, p2) -> p1 + p2).get(); //Integer num = dataSource.reduce(Integer::sum).get(); //3.輸出 System.out.println(num);//45 } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); } }
3. count
統計流中的元素數量

public class FinalOperation { public static void main(String[] args) { countUsage(); } public static void countUsage(){ //1.讀取數據源,得到流對象 Stream<Integer> dataSource = getDataSource(); //2.最終操作 獲取元素數量 Long num = dataSource.count(); //3.輸出 System.out.println(num);//10 } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); } }
4. forEach
迭代、遍歷流中的數據

public class FinalOperation { public static void main(String[] args) { forEachUsage(); } public static void forEachUsage(){ //1.讀取數據源,得到流對象 Stream<Integer> dataSource = getDataSource(); //2.最終操作 遍歷流中的數據 輸出 dataSource.forEach(System.out::print);//0123456789 } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); } }
5. max&min
獲取流中的最大/最小元素

public class FinalOperation { public static void main(String[] args) { maxAndMinUsage(); } //按照執行的對象比較的規則去進行大小的比較,然后得出流中最大、最小的數據 public static void maxAndMinUsage(){ //1.讀取數據源,得到流對象 Stream<Integer> dataSource = getDataSource(); //2.最終操作 獲取流中的最大、最小值 //Integer max = dataSource.max(Integer::compareTo).get(); //System.out.println(max);//9 Integer min = dataSource.min(Integer::compareTo).get(); System.out.println(min);//0 } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); } }
6. Matching
allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true
anyMatch:只要流中有任意的數據,滿足指定的規則,都會返回true
noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true

public static void main(String[] args) { matchingUsage(); } public static void matchingUsage(){ //1.讀取數據源,獲取Stream對象 Stream<Integer> dataSource = getDataSource(); //2.匹配的操作 //boolean b = dataSource.allMatch(e -> e>0); //System.out.println(b);//false 因為不是集合中所有的元素都大於0 還有一個等於0 //boolean b = dataSource.anyMatch(e -> e >= 9); //System.out.println(b);//true boolean b = dataSource.noneMatch(e -> e > 9); System.out.println(b);//true } //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象) public static Stream<Integer> getDataSource(){ //1.准備一個容器 List<Integer> dataSource = new ArrayList<>(); //2.向數據源中添加數據 Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //3.讀取數據源中的數據,得到Stream對象 return dataSource.stream(); }
7. find
findFirst:從流中獲取一個元素(是獲取的開頭元素)
findAny:從流中獲取一個元素(一般情況下,是獲取的開頭的元素)
這兩個方法,絕大部分情況下,是完全相同的,但是在多線程環境下,返回結果可能不一樣

public static void main(String[] args) { findUsage(); } public static void findUsage(){ //1.實例化一個集合 ArrayList<Integer> dataSource = new ArrayList<>(); Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); //2.findFirst演示 //Integer integer = dataSource.stream().findFirst().get();//串行流 //Integer integer = dataSource.parallelStream().findFirst().get();//並行流 //System.out.println(integer);//串行流或者是並行流結果都是0 //3.findAny演示 //Integer integer = dataSource.stream().findAny().get();//串行流 Integer integer = dataSource.parallelStream().findAny().get();//並行流 System.out.println(integer);//串行流是0、並行流結果為6 即不一定是0 }
8. IntStream
主要可以實現獲取流中int類型數據的最大值、最小值、平均值、和、數量
還可以獲取到一個對流中數據的分析結果(即一次獲取所有類型的值)

public static void main(String[] args) { intStreamUsage(); } public static void intStreamUsage(){ //1.准備一個int數組作為數據源 int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; //2.讀取數據到流中,獲取IntStream對象 IntStream stream = Arrays.stream(array); //3.輸出 //System.out.println(stream.max().getAsInt());//獲取最大值 9 //System.out.println(stream.min().getAsInt());//獲取最小值 0 //System.out.println(stream.sum());//獲取和 45 //System.out.println(stream.count());//獲取流中數據個數 10 //System.out.println(stream.average().getAsDouble());//獲取流中數據的平均值 4.5 //4.獲取到一個對流中數據的分析結果(即一次獲取所有類型的值) IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics(); System.out.println("最大值:"+intSummaryStatistics.getMax()+" 最小值:"+intSummaryStatistics.getMin());//最大值:9 最小值:0 System.out.println("平均值:"+intSummaryStatistics.getAverage()+" 和:"+intSummaryStatistics.getSum());//平均值:4.5 和:45 System.out.println("數量:"+intSummaryStatistics.getCount());//數量:10 }
四、中間操作
將數據從數據源中讀取到流中,就是對流中的數據進行各種各樣的操作、處理。中間操作可以連續操作,每一個操作的返回值都是一個Stream對象,可以繼續進行其他的操作,直到最終操作。
中間操作主要分為:filter、distinct、sorted、limit&skip、map&flatMap、Collections工具類
1. filter
條件過濾,僅保留流中滿足指定條件的數據,其他不滿足的數據都會被刪除。

//學生類:存儲於集合中的數據類型 private static class Student{ private String name; private int age; private int score; public Student(String name, int age, int score) { this.name = name; this.age = age; this.score = score; } //這里省略getter、setter、toString方法 } public static void main(String[] args) { filterUsage(); } public static void filterUsage(){ //1. 獲取數據源 Stream<Student> dataSource = getDataSource(); //2. 過濾掉集合中成績不合格的學生信息 dataSource.filter(s -> s.getScore()>=60).forEach(System.out::println); //Student{name='xiaoming', age=18, score=100} //Student{name='xiaoming', age=19, score=90} //Student{name='xiaoming', age=20, score=80} //Student{name='xiaoming', age=21, score=70} //Student{name='xiaoming', age=22, score=60} } //讀取數據源,將集合中存儲的數據,讀取到數據源中 public static Stream<Student> getDataSource(){ //1.實例化一個集合,存Student對象 ArrayList<Student> arrayList = new ArrayList<>(); //2.添加若干數據 Collections.addAll(arrayList, new Student("xiaoming",18,100), new Student("xiaoming",19,90), new Student("xiaoming",20,80), new Student("xiaoming",21,70), new Student("xiaoming",22,60), new Student("xiaoming",23,50), new Student("xiaoming",24,40) ); //3.讀取數據源,得到Stream對象 return arrayList.stream(); }
2. distinct
去除集合中重復的元素,這個方法沒有參數,去重的規則與HashSet相同。
(1)比較兩個對象的hashcode
(2)使用equals再來對比一下
這里要注意:實體類中需要重寫hashcode和equals方法,否則去重可能不會生效

//學生類:存儲於集合中的數據類型 private static class Student{ private String name; private int age; private int score; public Student(String name, int age, int score) { this.name = name; this.age = age; this.score = score; } //這里省略getter、setter、toString、hashcode、equals方法 } public static void main(String[] args) { distinctUsage(); } public static void distinctUsage(){ //1. 獲取數據源 Stream<Student> dataSource = getDataSource(); //2. 去重 要注意實體類Student中需要重寫equals和hashCode方法,否則去重不會生效 dataSource.distinct().forEach(System.out::println); //Student{name='xiaoming1', age=18, score=100} //Student{name='xiaoming2', age=20, score=80} //Student{name='xiaoming3', age=21, score=70} //Student{name='xiaoming4', age=22, score=60} //Student{name='xiaoming5', age=23, score=50} //Student{name='xiaoming6', age=24, score=40} } //讀取數據源,將集合中存儲的數據,讀取到數據源中 public static Stream<Student> getDataSource(){ //1.實例化一個集合,存Student對象 ArrayList<Student> arrayList = new ArrayList<>(); //2.添加若干數據 Collections.addAll(arrayList, new Student("xiaoming1",18,100), new Student("xiaoming1",18,100), new Student("xiaoming2",20,80), new Student("xiaoming3",21,70), new Student("xiaoming4",22,60), new Student("xiaoming5",23,50), new Student("xiaoming6",24,40) ); //3.讀取數據源,得到Stream對象 return arrayList.stream(); }
3. sorted
對流中的數據進行排序
(1)無參:sorted():將流中的數據,按照其對應的類實現的Comparable接口提供的比較規則進行排序
(2)有參:sorted(Comparator<T> comparator):將流中的數據,按照參數接口提供的比較規則進行排序

private static class Student implements Comparable<Student>{ private String name; private int age; private int score; public Student(String name, int age, int score) { this.name = name; this.age = age; this.score = score; } @Override public int compareTo(Student o) { return score-o.score; } //這里省略getter、setter、toString、hashcode、equals方法 } public static void main(String[] args) { sortedUsage(); } public static void sortedUsage(){ //1. 獲取數據源 Stream<Student> dataSource = getDataSource(); //2. 將流中的數據進行排序 (注意實體類要注意實現Comparable接口並重寫compareTo方法,否則會報錯) //dataSource.sorted().forEach(System.out::println); //Student{name='xiaoming6', age=24, score=40} //Student{name='xiaoming5', age=23, score=50} //Student{name='xiaoming4', age=22, score=60} //Student{name='xiaoming3', age=21, score=70} //Student{name='xiaoming2', age=20, score=80} //Student{name='xiaoming1', age=18, score=100} //Student{name='xiaoming1', age=18, score=100} //3. 對流中的數據按照自定義的規則進行排序 (按照年齡升序排列) dataSource.sorted((s1,s2)->s1.getAge()-s2.getAge()).forEach(System.out::println); //Student{name='xiaoming1', age=18, score=100} //Student{name='xiaoming1', age=18, score=100} //Student{name='xiaoming2', age=20, score=80} //Student{name='xiaoming3', age=21, score=70} //Student{name='xiaoming4', age=22, score=60} //Student{name='xiaoming5', age=23, score=50} //Student{name='xiaoming6', age=24, score=40} } //讀取數據源,將集合中存儲的數據,讀取到數據源中 public static Stream<Student> getDataSource(){ //1.實例化一個集合,存Student對象 ArrayList<Student> arrayList = new ArrayList<>(); //2.添加若干數據 Collections.addAll(arrayList, new Student("xiaoming1",18,100), new Student("xiaoming1",18,100), new Student("xiaoming2",20,80), new Student("xiaoming3",21,70), new Student("xiaoming4",22,60), new Student("xiaoming5",23,50), new Student("xiaoming6",24,40) ); //3.讀取數據源,得到Stream對象 return arrayList.stream(); }
4. limit&skip
limit:限制,截取流中指定數量的元素 skip:跳過流中的指定數量的元素 經常放在一起用

//實體類省略,參考上面即可 public static void main(String[] args) { limitAndSkipUsage(); } public static void limitAndSkipUsage(){ //1. 獲取數據源 Stream<Student> dataSource = getDataSource(); //2. 獲取成績的前5名 // dataSource.distinct() // .sorted((s1,s2)->s2.getScore()-s1.getScore()) // .limit(5) // .forEach(System.out::println); //3. 獲取成績為3-5名的 dataSource.distinct() .sorted((s1,s2)->s2.getScore()-s1.getScore()) .limit(5) .skip(2) .forEach(System.out::println); } //讀取數據源,將集合中存儲的數據,讀取到數據源中 public static Stream<Student> getDataSource(){ //1.實例化一個集合,存Student對象 ArrayList<Student> arrayList = new ArrayList<>(); //2.添加若干數據 Collections.addAll(arrayList, new Student("xiaoming1",18,100), new Student("xiaoming1",18,100), new Student("xiaoming2",20,80), new Student("xiaoming3",21,70), new Student("xiaoming4",22,60), new Student("xiaoming5",23,50), new Student("xiaoming6",24,40) ); //3.讀取數據源,得到Stream對象 return arrayList.stream(); }
5. map&flatMap
對流中的數據進行映射,用新的數據替換舊的數據
map最主要,就是來做元素的替換,其實map是一個元素的映射(將流中每一個元素替換成指定的元素)
flatMap也是元素的映射,flatMap是扁平化映射
扁平化映射:一般用在map映射完成后,流中的數據是一個容器,而我們需要對容器中的數據進行處理 此時使用扁平化映射,可以將流中的容器中的數據,直接讀取到流中
案例1:

public static void main(String[] args) { mapUsage(); } public static void mapUsage(){ //1. 獲取數據源 Stream<Student> dataSource = getDataSource(); //2. 實際需求:獲取所有學生的名字 //dataSource.map(Student::getName).forEach(System.out::println); //dataSource.map(s->s.getName()).forEach(System.out::println); //3. 實際需求:獲取所有學生的成績 注意:泛型中不能是基本數據類型,只能是包裝類 即下面的返回值應該為Stream<Integer> //dataSource.map(Student::getScore).forEach(System.out::println); //4. 實際需求:獲取所有學生的成績 IntSummaryStatistics intSummaryStatistics = dataSource.mapToInt(Student::getScore).summaryStatistics(); System.out.println(intSummaryStatistics.getMax()); } //讀取數據源,將集合中存儲的數據,讀取到數據源中 public static Stream<Student> getDataSource(){ //1.實例化一個集合,存Student對象 ArrayList<Student> arrayList = new ArrayList<>(); //2.添加若干數據 Collections.addAll(arrayList, new Student("xiaoming1",18,100), new Student("xiaoming1",18,100), new Student("xiaoming2",20,80), new Student("xiaoming3",21,70), new Student("xiaoming4",22,60), new Student("xiaoming5",23,50), new Student("xiaoming6",24,40) ); //3.讀取數據源,得到Stream對象 return arrayList.stream(); }
案例2:

public static void main(String[] args) { mapUsage(); } public static void mapUsage(){ //1.實例化一個字符串數組 String[] array = {"hello","world"}; //2.將字符串數組中的數據讀取到流中 Stream<String> stream = Arrays.stream(array); //3.需求:統計字符串數組中所有出現的字符 //stream.map(String::toCharArray).forEach(e->System.out.println(Arrays.toString(e))); //結果為 [h, e, l, l, o] [w, o, r, l, d] 兩個數組 不符合我們的要求 stream.map(s->s.split("")) .flatMap(Arrays::stream) .distinct() .forEach(System.out::println); //結果為h e l o w r d }
6. Collections工具類
Collectors是一個工具類,里面封裝了很多方法,可以很方便的獲取到一個Collector接口的實現類對象,從而可以使用collect()方法,對流中的數據,進行各種各樣的處理、整合。
常用方法:
Collectors.toList() 將流中的數據,聚合到一個List集合中
Collectors.toSet() 將流中的數據,聚合到一個Set集合中
Collectors.toMap() 將流中的數據,聚合到一個Map集合中
maxBy() 按照指定的規則,找到流中最大的元素,等同於max
minBy() 按照指定的規則,找到流中最小的元素,等同於min
joining() 將流中的數據拼接成一個字符串,注意:只能操作流中是String的數據
summingInt() 將流中的數據,映射成int類型的數據,並求和
averagingInt() 將流中的數據,映射成int類型的數據,並求平均值
summarizingInt() 將流中的數據,映射成int類型的數據,並獲取描述信息

public static void main(String[] args) { //1. 准備一個字符串數組,作為數據源 String[] dataSource = {"nihao","wo","shi","xxx"}; //2. 讀取數據源中的數據 Stream<String> stream = Arrays.stream(dataSource); //3. joining方法,只適用於 Stream<String> 這種流 //String collect = stream.collect(Collectors.joining());//拼接 //System.out.println(collect);//nihaowoshixxx //String collect = stream.collect(Collectors.joining(","));//拼接 按照逗號分隔 //System.out.println(collect);//nihao,wo,shi,xxx //tring collect = stream.collect(Collectors.joining(",","[","]"));//拼接 帶前綴、后綴 //System.out.println(collect);//[nihao,wo,shi,xxx] //4. summingInt Integer collect = stream.collect(Collectors.summingInt(String::length)); System.out.println(collect);//13 }
持續更新!!!
注意:本篇文章大多數內容來自bilibili網站千鋒教育,地址:https://www.bilibili.com/video/BV1fT4y177ui?p=6 本篇文章僅用於個人學習和總結,如有侵權,聯系刪除!