Stream流
Stream(流)是一個來自數據源的元素隊列並支持聚合操作:
- 元素是特定類型的對象,形成一個隊列。 Java中的Stream並不會存儲元素,而 是按需計算。
- 數據源 流的來源。 可以是集合,數組等。
- 聚合操作類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted 等。
Stream流操作的三個步驟:
-
創建Stream
一個數據源(如:集合、數組),獲取一個流
-
中間操作
一箇中間操作鏈,對數據源的數據進行處理
-
終止操作
一個終止操作,執行中間操作鏈,併產生結果
創建Stream步驟:
- 通過Collection系列集合提供的順序流stream()或並行流parallelStream()
- 通過Arrays中的靜態方法stream()獲取數據流
- 通過Stream類中的靜態方法of()
代碼實例:
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest01 {
public static void main(String[] args) {
//第一種方式:通過集合中的stream()方法創建Stream
List<String> list= Arrays.asList("紅太狼","灰太狼","喜羊羊");
Stream<String> stream=list.stream();
//通過集合中的parallelStream方法創建
Stream<String> stream2 = list.parallelStream();
//第二種方式:通過java.util.Arrays下的靜態方法stream創建Stream
Integer[] integer=new Integer[]{1,2,4};
//這裏需要注意的是Arrays中的stream方法裏面的參數需要一個數組,且數組的類型是一個引用類型或者是一個包裝類
Stream<Integer> stream3 = Arrays.stream(integer);
//第三種方式:通過Stream中的of方法,實際上這種方式創建Stream實際上間接的通過調用Arrays中的stream()靜態方法
Stream<String> stream4=Stream.of("a","b","c");
}
}
Stream的中間操作
篩選和切片
filter:過濾器
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",29);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//創建Stream
Stream<Employee> stream1 = list.stream();
//對stream1流進行過濾
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//過濾掉年齡小於19
return e.getAge() >= 19;
});
s.forEach((e-> System.out.println(e)));
}
}
class Employee {
private String id;
private String name;
private int age;
public Employee() {
}
public Employee(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
id.equals(employee.id) &&
name.equals(employee.name);
}
@Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
運行結果:
skip(n):指跳過Stream中存儲的前n條數據(包含第n條數據),返回後n條數據,如果n大於Stream中所有元素的個數,則返回空;(Employee類如上)
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",9);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//創建Stream
Stream<Employee> stream1 = list.stream();
//對stream1流進行過濾
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//過濾掉年齡小於19
return e.getAge() >= 19;
}).skip(2);
//s=s.skip(5);
s.forEach((e-> System.out.println(e)));
}
}
運行截圖:
distinct:篩選重複的元素,通過流生產元素的hashCode()和equals去除重複元素;
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",9);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//創建Stream
Stream<Employee> stream1 = list.stream();
//對stream1流進行過濾
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//過濾掉年齡小於19
return e.getAge() >= 19;
}).skip(2).distinct();
//s=s.skip(5);
s.forEach((e-> System.out.println(e)));
}
}
運行截圖:
排序:
sorted(Comparable)–自然排序
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest03 {
public static void main(String[] args) {
List<String> list= Arrays.asList("c","bbb","abc","bbbb");
Stream<String> stream = list.stream();
//即通過調用String方法中CompareTo,通過一個一個的比較字符的ASCLL值,首先比較首字符的ASCLL大小,相同的話再比較下一個
stream= stream.sorted();
stream.forEach(System.out::println);
}
}
sorted(Comparator)–定製排序
package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","哈哈",19);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",79);
Employee employee04=new Employee("yang","呵呵呵",79);
Employee employee05=new Employee("yang","hui",39);
Employee employee06=new Employee("yang","hui",29);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//創建Stream
Stream<Employee> stream1 = list.stream();
//對stream1流進行過濾
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//過濾掉年齡小於19
return e.getAge() >= 19;
});
//s=s.skip(5);
/*此處可以使用Lambda表達式,即s.sorted((o1,o2)->{
//升序排序,如果年齡相同,則按照姓名的長度排序
if (o1.getAge()==o2.getAge()){
return o1.getName().length()-o2.getName().length();
}
//按照年齡升序排序
return o1.getAge()-o2.getAge();
})
*/
s=s.sorted(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
//升序排序,如果年齡相同,則按照姓名的長度排序
if (o1.getAge()==o2.getAge()){
return o1.getName().length()-o2.getName().length();
}
//按照年齡升序排序
return o1.getAge()-o2.getAge();
}
});
s.forEach((e-> System.out.println(e)));
}
}
Stream中的map和flatMap方法:
- 流中的每一個數據,當做map方法的參數(接口),接口中抽象方法的參數,進行制定操作,最終得到一個結果,最後所有的結果返回去成爲一個流
- 流中的每一個數據當作參數,進行操作,得到的結果必須是一個流,最終會結合成一個流返回
package com.ysh.review01_Stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest04 {
public static void main(String[] args) {
Stream<String> stream=Stream.of("aaa","bbbb","ccccc");
//map方法是每一個數據當作一個流,即以上{aaa}、{bbbb}、{ccccc}各是一個Stream<Character>流集合,即達到得到多個Stream<Character>流集合
//可以理解爲Stream流中包含Stream<Character>流
//因爲這裏的testCharacter()的方法我返回的是一個Stream<Character>
//Stream<Stream<Character>> streamStream = stream.map((e) -> testCharacter(e));
Stream<Stream<Character>> streamStream = stream.map((e) -> {
List<Character> list = new ArrayList<>();
for (Character c : e.toCharArray()) {
list.add(c);
}
return list.stream();
});
streamStream.forEach((e)->{
e.forEach((e2)->{
System.out.println(e2);
});
});
Stream<String> stm=Stream.of("aaa","bbbb","ccccc");
//flatMap()方法即是把將得到的多個Stream<Character>流集合合併爲一個一個Stream<Character>流集合
Stream<Character> stream1=stm.flatMap(StreamTest04::testCharacter);
//streamStream.forEach(System.out::println);
System.out.println("---------------");
stream1.forEach(System.out::println);
}
//返回一個Stream
public static Stream<Character> testCharacter(String str){
List<Character> list=new ArrayList<>();
for (Character c:str.toCharArray()){
list.add(c);
}
Stream<Character> stream=list.stream();
return stream;
}
}
終止操作
查找與匹配
- allMatch:檢查是否匹配所有元素;
- anyMatch:檢查是否至少匹配一個元素;
- noneMatch:檢查是否沒有匹配所有元素;
- findFirst:返回第一個元素;
- findAny:返回當前流中的任意元素;
- count:返回流中元素的總個數;
- max:返回流中最大值;
- min:返回流中最小值;
代碼實例:
package com.ysh.review01_Stream;
import java.util.Optional;
import java.util.stream.Stream;
/**
* Stream中的終止操作
*/
public class StreamTest06 {
public static void main(String[] args) {
//獲取Stream
Stream<String> stm1=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//allMatch()方法裏面的參數是一個斷言式接口,即實現必須重寫test()方法
boolean b1 = stm1.allMatch((t) -> {
//檢查是否匹配所有元素
return t.length() > 2;
});
Stream<String> stm2=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
boolean b2=stm2.anyMatch((t) -> {
//檢查是否至少匹配一個元素
return t.length() > 2;
});
Stream<String> stm3=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
boolean b3=stm3.noneMatch((t) -> {
//檢查是否沒有匹配所有元素
return t.length() > 2;
});
Stream<String> stm4=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//得到流中的第一個元素
Optional<String> first = stm4.findFirst();
//輸出
System.out.println(first.get());
Stream<String> stm5=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回當前流中的任意元素
Optional<String> any = stm5.findAny();
System.out.println(any.get());
Stream<String> stm6=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//放回流中元素的總個數
long count = stm6.count();
System.out.println(count);
Stream<String> stm7=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回流中最大值,即長度最長,長度相同則比較ASCLL值大小
Optional<String> max = stm7.max((s1, s2) -> {
if (s1.length()==s2.length()){
return s1.compareTo(s2);
}
return s1.length() - s2.length();
});
System.out.println(max.get());
Stream<String> stm8=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回流中最小值,即長度最短,長度相同則比較ASCLL值大小
Optional<String> min = stm8.min((s1, s2) -> {
if (s1.length() == s2.length()) {
return s2.compareTo(s1);
}
return s1.length() - s2.length();
});
System.out.println(min.get());
System.out.println(b3);
}
}
收集:
收集-將流轉換爲其他形式,接收一個Collertor接口的實現,用於給Stream中元素做 彙總的方法
- List:把流中所有元素收集到List中,使用.collect(Collectors.toList());
- Set:把流中所有元素收集到Set中,刪除重複項,使用.collect(Collectors.toSet());
- Map:把流中所有元素收集到Map中,當出現相同的key時會拋異常,使用 .collect(Collectors.toMap());
- 使用collect方法求流中共有幾條數據,使用.collect(Collectors.counting())
- 使用collect方法求平均數,使用.collect(Collectors.averagingInt();
- 使用collect方法求某個變量的總和,使用.collect(Collectors.summingDouble());
- 使用collect方法且某個變量中值的最大值,使用.collect(Collectors.maxBy());
代碼實例:
package com.ysh.review01_Stream.one;
import java.util.*;
import java.util.stream.Collectors;
public class StreamTest07 {
public static void main(String[] args) {
Student stu1=new Student("1","hhhh",18);
Student stu2=new Student("2","hhhhh",19);
Student stu3=new Student("3","oooooo",19);
Student stu4=new Student("4","aaaaa",19);
List<Student> list = Arrays.asList(stu1,stu2,stu3,stu4);
//獲取所有學生的姓名流,並且存儲再List集合中
List<String> collect = list.stream().map((e) -> {
return e.getName();
}).collect(Collectors.toList());
System.out.println(collect);
Set<String> set = list.stream().map((e) -> {
return e.getName();
}).collect(Collectors.toSet());
System.out.println(collect);
//將學生的姓名和年齡放入到一個集合中,當出現相同的key是會拋出一個java.lang.IllegalStateException: Duplicate key異常
Map<String, Integer> map = list.stream().collect(Collectors.toMap((e) -> e.getName(), (e2) -> e2.getAge()));
System.out.println(map);
//運用collect輸出所有學生的總數
Long count2 = list.stream().collect(Collectors.counting());
System.out.println(count2);
//運用collect方法計算所有學生的平均年齡
Double collect1 = list.stream().collect(Collectors.averagingDouble((n) -> n.getAge()));
System.out.println(collect1);
//運用collect方法求所有學生的年齡之和
int agesum=list.stream().collect(Collectors.summingInt((e)->e.getAge()));
System.out.println(agesum);
//運用collect方法求所有學生中年齡最大的
Optional<Student> max2 = list.stream().collect(Collectors.maxBy((a1, a2) -> a1.getAge() - a2.getAge()));
System.out.println(max2.get());
}
}
class Student {
private String id;
private String name;
private int age;
public Student(){
}
public Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
id.equals(student.id) &&
name.equals(student.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age);
}
@Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
最後
感謝你看到這裏,文章有什麼不足還請指正,覺得文章對你有幫助的話記得給我點個贊!