流(Stream):是數據渠道,用於操做數據源(集合、數組等)所生成的元素序列。java
「集合講的是數據,流講的是計算」數組
① Stream 本身不會存儲元素。
② Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。
③ Stream 操做是延遲執行的。這意味着他們會等到須要結果的時候才執行。dom
//建立 Stream @Test public void test1(){ //1.Collection 提供了兩個方法 stream() 與 parallelStream() List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); //2.經過 Arrays 中的 stream() 獲取一個數組流 Employee[] employees = new Employee[10]; Stream<Employee> stream2 = Arrays.stream(employees); //3. 經過 Stream 類中靜態方法 of() List<String> list1 = Arrays.asList("12", "as", "df"); Stream stream3 = Stream.of(list1); //4. 建立無限流 //迭代 Stream stream4 = Stream.iterate(1, x -> x + 2); stream4.limit(10).forEach(System.out::println); //生成 Stream stream5 = Stream.generate(Math::random); stream5.limit(5).forEach(System.out::println); }
多箇中間操做能夠鏈接起來造成一個流水線,除非流水線上觸發終止操做,不然中間操做不會執行任何的處理!而在終止操做時一次性所有處理,稱爲「惰性求值」ide
方法 | 描述 |
filter(Predicate p) | 接收Lambda ,從流中排除某些元素 |
distinct() | 篩選,經過流所生成元素的hashCode() 和equals() 去除重複元素 |
limit(long maxSize) | 截斷流,使其元素不超過給定數量 |
skip(long n) | 跳過元素,返回一個扔掉了前n 個元素的流。若流中元素不足n 個,則返回一個空流。與limit(n) 互補 |
//2. 中間操做 List<Employee> employees = Arrays.asList( new Employee("張三", 20), new Employee("李四", 50), new Employee("王五", 40), new Employee("王五", 40), new Employee("王五", 40), new Employee("趙六", 10), new Employee("王琦", 8), new Employee("李逵", 4) ); /** * 篩選與切片 * filter(Predicate p) :接收Lambda ,從流中排除某些元素。 * distinct() :篩選,經過流所生成元素的hashCode() 和equals() 去除重複元素 * limit(long maxSize):截斷流,使其元素不超過給定數量。 * skip(long n):跳過元素,返回一個扔掉了前n 個元素的流。若流中元素不足n 個,則返回一個空流。與limit(n) 互補 */ //內部迭代:由StreamAPI本身完成 //filter(Predicate p) :接收Lambda ,從流中排除某些元素。 @Test public void test2() { /*多箇中間操做能夠鏈接起來造成一個流水線,除非流水 線上觸發終止操做,不然中間操做不會執行任何的處理! 而在終止操做時一次性所有處理,稱爲「惰性求值」*/ //中間操做:不會執行任何操做 Stream<Employee> s = employees.stream().filter((e) -> { System.out.println("Stream API中間操做!"); return e.getAge() > 25; }); //終止操做:一次性操做所有操做 s.forEach(System.out:: println); } //外部迭代 @Test public void test3() { Iterator<Employee> it = employees.iterator(); while (it.hasNext()) { Employee next = it.next(); System.out.println(next); } } //limit(long maxSize):截斷流,使其元素不超過給定數量。 @Test public void test4() { employees.stream() .filter(e -> e.getAge() > 30) .limit(3) .forEach(System.out:: println); //運行結果 /*Employee{name='李四', age=50} Employee{name='王五', age=40} Employee{name='王五', age=40}*/ } //skip(long n):跳過元素,返回一個扔掉了前n 個元素的流。若流中元素不足n 個,則返回一個空流。與limit(n) 互補 @Test public void test5() { employees.stream() .filter(e -> e.getAge() > 30) .skip(1) .forEach(System.out:: println); //運行結果 /*Employee{name='王五', age=40} Employee{name='王五', age=40} Employee{name='王五', age=40}*/ } //distinct() :篩選,經過流所生成元素的hashCode() 和equals() 去除重複元素 @Test public void test6() { employees.stream() .filter(e -> e.getAge() > 30) .distinct() .forEach(System.out:: println); //運行結果 /*Employee{name='李四', age=50} Employee{name='王五', age=40}*/ }
方法 | 描述 |
---|---|
map(Functionf) | 接收一個函數做爲參數,該函數會被應用到每一個元素上,並將其映射成一個新的元素 |
mapToDouble(ToDoubleFunction f) | 接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的DoubleStream |
mapToInt(ToIntFunction f) | 接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的IntStream |
mapToLong(ToLongFunction f) | 接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的LongStream |
flatMap(Function f) | 接收一個函數做爲參數,將流中的每一個值都換成另外一個流,而後把全部流鏈接成一個流 |
/** * 映射 * map(Functionf) :接收一個函數做爲參數,該函數會被應用到每一個元素上,並將其映射成一個新的元素。 * mapToDouble(ToDoubleFunction f) :接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的DoubleStream。 * mapToInt(ToIntFunction f) :接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的IntStream。 * mapToLong(ToLongFunction f) :接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的LongStream。 * flatMap(Function f) :接收一個函數做爲參數,將流中的每一個值都換成另外一個流,而後把全部流鏈接成一個流 */ @Test public void test7() { //map(Functionf) :接收一個函數做爲參數,該函數會被應用到每一個元素上,並將其映射成一個新的元素。 List<String> list = Arrays.asList("aaa", "bbb", "ccc"); list.stream() .map(str -> str.toUpperCase()) .forEach(System.out:: print);//AAABBBCCC System.out.println("-------------------------"); employees.stream() .map(Employee:: getName) .forEach(System.out:: print);//張三李四王五王五王五趙六王琦李逵 System.out.println("-------------------------"); //mapToInt(ToIntFunction f) :接收一個函數做爲參數,該函數會被應用到每一個元素上,產生一個新的IntStream。 IntStream is = employees.stream() .mapToInt(Employee:: getAge); is.forEach(System.out::println); System.out.println("-------------------------"); //flatMap(Function f) :接收一個函數做爲參數,將流中的每一個值都換成另外一個流,而後把全部流鏈接成一個流 list.stream() .flatMap(TestStreamAPI1:: filterCharacter) .forEach(System.out:: println); } public static Stream<Character> filterCharacter(String str) { List<Character> list = new ArrayList<>(); for (Character c : str.toCharArray()) { list.add(c); } return list.stream(); }
方法 | 描述 |
---|---|
sorted() | 產生一個新流,其中按天然順序排序 |
sorted(Comparator comp) | 產生一個新流,其中按比較器順序排序 |
/** * 排序 * sorted() 產生一個新流,其中按天然順序排序(Comparable) sorted(Comparator comp) 產生一個新流,其中按比較器順序排序( Comparator) */ @Test public void test8(){ //sorted() 產生一個新流,其中按天然順序排序(Comparable) List<String> list = Arrays.asList("aaa", "eee", "ccc","yyy"); list.stream() .sorted() .forEach(System.out::print);//aaaccceeeyyy System.out.println("-----------------"); //sorted(Comparator comp) 產生一個新流,其中按比較器順序排序( Comparator) employees.stream() .sorted((e1,e2)->{ if (e1.getAge() == e2.getAge()){ return e1.getName().compareTo(e2.getName()); }else{ return Integer.compare(e1.getAge(), e2.getAge()); } }).forEach(System.out::println); }
方法 | 描述 |
---|---|
allMatch(Predicate p) | 檢查是否匹配全部元素 |
anyMatch(Predicate p) | 檢查是否至少匹配一個元素 |
noneMatch(Predicatep) | 檢查是否沒有匹配全部元素 |
findFirst() | 返回第一個元素 |
findAny() | 返回當前流中的任意元素 |
count() | 返回流中元素總數 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 內部迭代(使用Collection 接口須要用戶去作迭代,稱爲外部迭代。相反,Stream API 使用內部迭代——它幫你把迭代作了) |
/** * 查找與匹配 * allMatch(Predicate p) 檢查是否匹配全部元素 anyMatch(Predicate p) 檢查是否至少匹配一個元素 noneMatch(Predicatep) 檢查是否沒有匹配全部元素 findFirst() 返回第一個元素 findAny() 返回當前流中的任意元素 count() 返回流中元素總數 max(Comparator c) 返回流中最大值 min(Comparator c) 返回流中最小值 forEach(Consumer c) 內部迭代(使用Collection 接口須要用戶去作迭代,稱爲外部迭代。相反,Stream API 使用內部迭代——它幫你把迭代作了) */ @Test public void test9(){ boolean b1 = employees.stream() .allMatch(e -> e.getAge() > 20); System.out.println(b1);//false boolean b2 = employees.stream() .anyMatch(e -> e.getAge() > 20); System.out.println(b2);//true boolean b3 = employees.stream() .noneMatch(e -> e.getAge() > 20); System.out.println(b3);//false Optional<Employee> op1 = employees.stream() .findFirst(); System.out.println(op1.get());//Employee{name='張三', age=20} //並行流與串行流 /*並行流就是把一個內容分紅多個數據塊,並用不一樣的線程分別處理每一個數據塊的流。 Java 8 中將並行進行了優化,咱們能夠很容易的對數據進行並行操做。 Stream API 能夠聲明性地經過parallel() 與sequential() 在並行流與順序流之間進行切換。*/ Optional<Employee> op2 = employees.stream().parallel() .findAny(); System.out.println(op2.get());//Employee{name='趙六', age=10} Optional<Employee> op3 = employees.stream().sequential() .findAny(); System.out.println(op3.get());//Employee{name='張三', age=20} long num = employees.stream() .count(); System.out.println(num);//8 Optional<Employee> op4 = employees.stream() .max(Comparator.comparingInt(Employee:: getAge)); System.out.println(op4.get());//Employee{name='李四', age=50} Optional<Employee> op5 = employees.stream() .min(Comparator.comparingInt(Employee:: getAge)); System.out.println(op5.get());//Employee{name='李逵', age=4} }
方法 | 描述 |
---|---|
reduce(T iden, BinaryOperator b) | 能夠將流中元素反覆結合起來,獲得一個值。返回T |
reduce(BinaryOperator b) | 能夠將流中元素反覆結合起來,獲得一個值。返回Optional<T> |
/** * 歸約 * reduce(T iden, BinaryOperator b) 能夠將流中元素反覆結合起來,獲得一個值。返回T reduce(BinaryOperator b) 能夠將流中元素反覆結合起來,獲得一個值。返回Optional<T> */ @Test public void test10(){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); Integer sum = list.stream() .reduce(0, (x, y) -> x + y); System.out.println(sum); //21 System.out.println("-----------------------------"); Optional<Integer> op = employees.stream() .map(Employee:: getAge) .reduce(Integer:: sum); System.out.println(op.get());//212 }
方法 | 描述 |
---|---|
collect(Collector c) | 將流轉換爲其餘形式。接收一個Collector接口的 實現,用於給Stream中元素作彙總的方法 |
Collector 接口中方法的實現決定了如何對流執行收集操做(如收集到List、Set、Map)。可是Collectors 實用類提供了不少靜態方法,能夠方便地建立常見收集器實例,具體方法與實例以下表:函數
方法 | 返回類型 | 做用 |
---|---|---|
toList | List<T> | 把流中元素收集到List |
List<Employee>emps=list.stream().collect(Collectors.toList()); | ||
toSet | Set<T> | 把流中元素收集到Set |
Set<Employee>emps=list.stream().collect(Collectors.toSet()); | ||
toCollection | Collection<T> | 把流中元素收集到建立的集合 |
Collection<Employee>emps=list.stream().collect(Collectors.toCollection(ArrayList::new)); | ||
counting | Long | 計算流中元素的個數 |
long count=list.stream().collect(Collectors.counting()); | ||
summingInt | Integer | 對流中元素的整數屬性求和 |
inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary)); | ||
averagingInt | Double | 計算流中元素Integer屬性的平均值 |
doubleavg=list.stream().collect(Collectors.averagingInt(Employee::getSalary)); | ||
summarizingInt | IntSummaryStatistics | 收集流中Integer屬性的統計值。如:平均值 |
IntSummaryStatisticsiss=list.stream().collect(Collectors.summarizingInt(Employee::getSalary)); | ||
joining | String | 鏈接流中每一個字符串 |
Stringstr=list.stream().map(Employee::getName).collect(Collectors.joining()); | ||
maxBy | Optional<T> | 根據比較器選擇最大值 |
Optional<Emp>max=list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary))); | ||
minBy | Optional<T> | 根據比較器選擇最小值 |
Optional<Emp>min=list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary))); | ||
reducing | 歸約產生的類型 | 從一個做爲累加器的初始值開始,利用BinaryOperator與流中元素逐個結合,從而歸約成單個值 |
inttotal=list.stream().collect(Collectors.reducing(0,Employee::getSalar,Integer::sum)); | ||
collectingAndThen | 轉換函數返回的類型 | 包裹另外一個收集器,對其結果轉換函數 |
inthow=list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size)); | ||
groupingBy | Map<K,List<T>> | 根據某屬性值對流分組,屬性爲K,結果爲V |
Map<Emp.Status, List<Emp>> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus)); | ||
partitioningBy | Map<Boolean,List<T>> | 根據true或false進行分區 |
Map<Boolean,List<Emp>>vd=list.stream().collect(Collectors.partitioningBy(Employee::getManage)); |
/** * 收集 * collect(Collector c) 將流轉換爲其餘形式。接收一個Collector接口實現,用於給Stream中元素作彙總的方法 */ @Test public void test11(){ List<String> list = employees.stream() .map(Employee:: getName) .collect(Collectors.toList()); list.forEach(System.out::print);//張三李四王五王五王五趙六王琦李逵 System.out.println("-----------------------"); Set<String> set = employees.stream() .map(Employee:: getName) .collect(Collectors.toSet()); set.forEach(System.out::print);//李四張三王琦王五趙六李逵 System.out.println("-----------------------"); HashSet hset = employees.stream() .map(Employee:: getName) .collect(Collectors.toCollection(HashSet::new)); hset.forEach(System.out::print);//李四張三王琦王五趙六李逵 } @Test public void test12(){ //總數 long count = employees.stream() .collect(Collectors.counting()); System.out.println(count);//8 //平均值 Double avg = employees.stream() .collect(Collectors.averagingInt(Employee::getAge)); System.out.println(avg);//26.5 //總和 int sum = employees.stream() .collect(Collectors.summingInt(Employee:: getAge)); System.out.println(sum);//212 //最大值 Optional<Employee> max = employees.stream() .collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()))); System.out.println(max.get());//Employee{name='李四', age=50} //最小值 Optional<Integer> min = employees.stream() .map(Employee:: getAge) .collect(Collectors.minBy(Integer:: compare)); System.out.println(min.get());//4 } //分組 @Test public void test13(){ Map<String,List<Employee>> map = employees.stream() .collect(Collectors.groupingBy(Employee:: getName)); System.out.println(map.toString()); /*{李四=[Employee{name='李四', age=50}], 張三=[Employee{name='張三', age=20}], 王琦=[Employee{name='王琦', age=8}], 王五=[Employee{name='王五', age=40}, Employee{name='王五', age=40}, Employee{name='王五', age=40}], 趙六=[Employee{name='趙六', age=10}], 李逵=[Employee{name='李逵', age=4}]}*/ } //分區 @Test public void test14() { Map<Boolean, List<Employee>> map = employees.stream() .collect(Collectors.partitioningBy((e) ->e.getAge() > 30)); System.out.println(map); /*{ false=[Employee{name='張三', age=20}, Employee{name='趙六', age=10}, Employee{name='王琦', age=8}, Employee{name='李逵', age=4}], true=[Employee{name='李四', age=50}, Employee{name='王五', age=40}, Employee{name='王五', age=40}, Employee{name='王五', age=50}]}*/ } //summarizingInt IntSummaryStatistics 收集流中Integer屬性的統計值。如:平均值 @Test public void test15(){ DoubleSummaryStatistics ds = employees.stream() .collect(Collectors.summarizingDouble(Employee:: getAge)); System.out.println(ds.getAverage());//27.75 System.out.println(ds.getCount());//8 System.out.println(ds.getMax());//50.0 System.out.println(ds.getMin());//4.0 System.out.println(ds.getSum());//222.0 } //joining鏈接流中每一個字符串 @Test public void test16(){ String str = employees.stream() .map(Employee:: getName) .collect(Collectors.joining(",", "---", "===")); System.out.println(str);//---張三,李四,王五,王五,王五,趙六,王琦,李逵=== }