【java】集合流式程式設計總結
在具體的介紹之前,先總結一波常用的寫法,有基礎的可以直接拿來用,沒有基礎的可以先跳過,看完下面的基礎再回來看
public static void main(String[] args) { List<User> userList = new ArrayList<>(); userList.addAll(Arrays.asList( new User(1, 11, "張三"), new User(1, 11, "張三"), new User(2, 22, "李四"),View Codenew 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工具類一些常用方法】 //【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()); }
一、集合流的簡介
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(); } }View Code
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(); } }View Code
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(); } }View Code
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(); } }View Code
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(); } }View Code
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(); }View Code
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 }View Code
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 }View Code
四、中間操作
將資料從資料來源中讀取到流中,就是對流中的資料進行各種各樣的操作、處理。中間操作可以連續操作,每一個操作的返回值都是一個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(); }View Code
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(); }View Code
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(); }View Code
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(); }View Code
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(); }View Code
案例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 }View Code
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 }View Code
持續更新!!!
注意:本篇文章大多數內容來自bilibili網站千鋒教育,地址:https://www.bilibili.com/video/BV1fT4y177ui?p=6 本篇文章僅用於個人學習和總結,如有侵權,聯絡刪除!