|
| 1 | +<!-- toc --> |
| 2 | + |
| 3 | +# Stream流概述 |
| 4 | + |
| 5 | +Stream流是一个来自数据源的元素队列 |
| 6 | + |
| 7 | +Stream流其实是一个集合元素的函数模型,它不是集合,也不是数据结构,其本身不存储任何元素 |
| 8 | + |
| 9 | +Stream 代表了来自某个源的对象的序列,这些序列支持聚集操作。 |
| 10 | + |
| 11 | +下面是 Stream 的一些特性: |
| 12 | + |
| 13 | +- 元素序列:Stream 以序列的形式提供了特定类型的元素的集合。根据需求,它可以获得和计算元素,但不会储存任何元素。 |
| 14 | +- 源:Stream 可以将集合、数组和 I/O 资源作为输入源。 |
| 15 | +- 聚集操作:Stream 支持诸如 `filter`、`map`、`limit`、`reduce` 等的聚集操作。 |
| 16 | +- 流水技术:许多 Stream 操作返回了流本身,故它们的返回值可以以流水的行式存在。这些操作称之为中间操作,并且它们的功能就是负责输入、处理和向目标输出。`collect()` 方法是一个终结操作,通常存在于流水线操作的末端,来标记流的结束。 |
| 17 | +- 自动迭代:Stream 的操作可以基于已提供的源元素进行内部的迭代,而集合则需要显式的迭代 |
| 18 | + |
| 19 | +# 流的获取 |
| 20 | + |
| 21 | +`java.util.stream.Stream<T>`是Java 8新加入的最常用的流接口(不是函数式接口) |
| 22 | + |
| 23 | +有两种获取流的方式: |
| 24 | + |
| 25 | +* 所有的`Collection`集合(不包括Map集合)都可以通过 `stream` 默认方法获取流 |
| 26 | + |
| 27 | + ```java |
| 28 | + default Stream<E> stream() |
| 29 | + ``` |
| 30 | + |
| 31 | +* Stream接口的静态方法`of`可以获取数组对应的流 |
| 32 | + |
| 33 | + ```java |
| 34 | + static <T> Stream<T> of(T...values) |
| 35 | + ``` |
| 36 | + |
| 37 | +## 根据Collection获取流 |
| 38 | + |
| 39 | +```java |
| 40 | +/* |
| 41 | + 把集合转换为Stream流 |
| 42 | + */ |
| 43 | +List<String> list = new ArrayList<>(); |
| 44 | +Stream<String> stream1 = list.stream(); |
| 45 | + |
| 46 | +Set<String> set = new HashSet<>(); |
| 47 | +Stream<String> stream2 = set.stream(); |
| 48 | + |
| 49 | +Map<String,String> map = new HashMap<>(); |
| 50 | +//获取键,存储到Set集合,再转换为流 |
| 51 | +Set<String> keySet = map.keySet(); |
| 52 | +Stream<String> stream3 = keySet.stream(); |
| 53 | + |
| 54 | +//获取值,存储到Collection集合中 |
| 55 | +Collection<String> values = map.values(); |
| 56 | +Stream<String> stream4 = values.stream(); |
| 57 | + |
| 58 | +//获取键值对,存储到set集合 |
| 59 | +Set<Map.Entry<String, String>> entries = map.entrySet(); |
| 60 | +Stream<Map.Entry<String, String>> stream5 = entries.stream(); |
| 61 | +``` |
| 62 | + |
| 63 | +## 根据数组获取流 |
| 64 | + |
| 65 | +```java |
| 66 | +/* |
| 67 | + 把数组转换为Stream流 |
| 68 | + */ |
| 69 | +Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5); |
| 70 | +//可变参数可以传递数组 |
| 71 | +Integer[] arr ={1,2,3,4,5}; |
| 72 | +Stream.of(arr); |
| 73 | +``` |
| 74 | + |
| 75 | +# Stream流的常用方法 |
| 76 | + |
| 77 | +Stream流的方法可以分为以下两种 |
| 78 | + |
| 79 | +1. 延迟方法:返回值类型仍然是Stream接口自身类型的方法,支持链式调用 |
| 80 | +2. 终结方法:返回值类型不再是Stream接口自身类型的方法,不再支持链式调用,终结方法包括count和forEach方法 |
| 81 | + |
| 82 | +## forEach |
| 83 | + |
| 84 | +void forEach(Consumer<? super T> action); |
| 85 | + |
| 86 | +该方法接收一个Consumer接口函数,将每一个流元素交给函数进行处理(消费数据) |
| 87 | + |
| 88 | +forEach方法是终结方法,用来遍历流中的数据,遍历之后就不能继续调用Stream流中其他方法 |
| 89 | + |
| 90 | +使用如下 |
| 91 | + |
| 92 | +```java |
| 93 | +package com.hs_vae.Stream; |
| 94 | + |
| 95 | +import java.util.Arrays; |
| 96 | +/* |
| 97 | + void forEach(Consumer<? super T> action); |
| 98 | + 该方法接收一个Consumer接口函数,将每一个流元素交给函数进行处理(消费数据) |
| 99 | + forEach方法是终结方法,用来遍历流中的数据,遍历之后就不能继续调用Stream流中其他方法 |
| 100 | + */ |
| 101 | +public class Demo02Stream_forEach { |
| 102 | + public static void main(String[] args) { |
| 103 | + Arrays.asList(1,2,3).stream().forEach(System.out::println); //输出1 2 3 |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +``` |
| 108 | + |
| 109 | +## filter |
| 110 | + |
| 111 | +Stream流中的filter方法用于对Stream流中的数据进行过滤 |
| 112 | + |
| 113 | +Stream<T> filter(Predicate<? super T> predicate); |
| 114 | + |
| 115 | +Predicate中的抽象方法: |
| 116 | + |
| 117 | + boolean test(T t) |
| 118 | + |
| 119 | +使用如下 |
| 120 | + |
| 121 | +```java |
| 122 | +package com.hs_vae.Stream; |
| 123 | + |
| 124 | +import java.util.Arrays; |
| 125 | + |
| 126 | +/* |
| 127 | + Stream流中的filter方法用于对Stream流中的数据进行过滤 |
| 128 | + Stream<T> filter(Predicate<? super T> predicate); |
| 129 | + Predicate中的抽象方法: |
| 130 | + boolean test(T t) |
| 131 | + */ |
| 132 | +public class Demo03Stream_filter { |
| 133 | + public static void main(String[] args) { |
| 134 | + //创建一个List集合对于小于3的元素进行过滤 |
| 135 | + Arrays.asList(1,2,3,4,5).stream().filter((x)->x>3).forEach(System.out::println); |
| 136 | + } |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | +## map |
| 141 | + |
| 142 | +Stream流中的map方法,将流中的元素映射到另一个流中 |
| 143 | + |
| 144 | +<R> Stream<R> map(Function<? super T,? extends R> mapper); |
| 145 | + |
| 146 | +函数式接口Function中的抽象方法: |
| 147 | + |
| 148 | + R apply(T t) 根据类型T的参数转换为类型R的结果 |
| 149 | + |
| 150 | +使用如下 |
| 151 | + |
| 152 | +```java |
| 153 | +package com.hs_vae.Stream; |
| 154 | + |
| 155 | +import java.util.Arrays; |
| 156 | +import java.util.List; |
| 157 | + |
| 158 | +/* |
| 159 | + Stream流中的map方法,将流中的元素映射到另一个流中 |
| 160 | + <R> Stream<R> map(Function<? super T,? extends R> mapper); |
| 161 | + 函数式接口Function中的抽象方法: |
| 162 | + R apply(T t) 根据类型T的参数转换为类型R的结果 |
| 163 | + */ |
| 164 | +public class Demo04Stream_map { |
| 165 | + public static void main(String[] args) { |
| 166 | + //定义一个List集合 |
| 167 | + List<Integer> list = Arrays.asList(1, 2, 3); |
| 168 | + //使用map方法由1,2,3转换2,4,6即变成2倍并遍历输出 |
| 169 | + list.stream().map(x->x*2).forEach(System.out::println); |
| 170 | + } |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +## count |
| 175 | + |
| 176 | +Stream流中的count方法用于统计Stream流中元素的个数 |
| 177 | + |
| 178 | +long count(); |
| 179 | + |
| 180 | +count方法是终结方法,所以使用后不能再继续调用Stream流中的其他方法 |
| 181 | + |
| 182 | +使用如下 |
| 183 | + |
| 184 | +```java |
| 185 | +package com.hs_vae.Stream; |
| 186 | + |
| 187 | +import java.util.Arrays; |
| 188 | + |
| 189 | +/* |
| 190 | + Stream流中的count方法用于统计Stream流中元素的个数 |
| 191 | + long count(); |
| 192 | + count方法是终结方法,所以使用后不能再继续调用Stream流中的其他方法 |
| 193 | + */ |
| 194 | +public class Demo05Stream_count { |
| 195 | + public static void main(String[] args) { |
| 196 | + long count = Arrays.asList(1, 2, 3).stream().count(); |
| 197 | + System.out.println(count); //3 |
| 198 | + } |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +## limit |
| 203 | + |
| 204 | +Stream流中的常用方法limit用于截取流中前n个元素 |
| 205 | + |
| 206 | +Stream<T> limit(long maxSize); |
| 207 | + |
| 208 | +使用如下 |
| 209 | + |
| 210 | +```java |
| 211 | +package com.hs_vae.Stream; |
| 212 | + |
| 213 | +import java.util.Arrays; |
| 214 | + |
| 215 | +/* |
| 216 | + Stream流中的常用方法limit用于截取流中前n个元素 |
| 217 | + */ |
| 218 | +public class Demo06Stream_limit { |
| 219 | + public static void main(String[] args) { |
| 220 | + //采用链式编程,定义一个集合转换为流,调用limit方法截取前2个元素并遍历输出 |
| 221 | + Arrays.asList(1,2,3,4).stream().limit(2).forEach(System.out::println); //1 2 |
| 222 | + } |
| 223 | +} |
| 224 | +``` |
| 225 | + |
| 226 | +## skip |
| 227 | + |
| 228 | +Stream流中的skip方法用于跳过前n个元素 |
| 229 | + |
| 230 | +Stream<T> skip(long n); |
| 231 | + |
| 232 | +使用skip方法获取一个截取之后新的流 |
| 233 | + |
| 234 | +使用如下 |
| 235 | + |
| 236 | +```java |
| 237 | +package com.hs_vae.Stream; |
| 238 | + |
| 239 | +import java.util.Arrays; |
| 240 | +import java.util.List; |
| 241 | +import java.util.stream.Stream; |
| 242 | + |
| 243 | +/* |
| 244 | + Stream流中的skip方法用于跳过前n个元素 |
| 245 | + 使用skip方法获取一个截取之后新的流 |
| 246 | + */ |
| 247 | +public class Demo07Stream_skip { |
| 248 | + public static void main(String[] args) { |
| 249 | + //定义一个集合里面存储4个数字并转换为一个流stream1 |
| 250 | + Stream<Integer> stream1 = Arrays.asList(1, 2, 3, 4).stream(); |
| 251 | + //使用skip方法跳过前2个元素,并返回一个新的流stream2 |
| 252 | + Stream<Integer> stream2 = stream1.skip(2); |
| 253 | + //在跳过之后的新流中遍历输出流中元素 |
| 254 | + stream2.forEach(System.out::println); |
| 255 | + } |
| 256 | +} |
| 257 | +``` |
| 258 | + |
| 259 | +## concat |
| 260 | + |
| 261 | +Stream流中的静态方法concat用于把流组合到一起 |
| 262 | + |
| 263 | +static <T> Stream<T> concat(Stream(? extends T) a,Stream(? extends T) b) |
| 264 | + |
| 265 | +使用如下 |
| 266 | + |
| 267 | +```java |
| 268 | +package com.hs_vae.Stream; |
| 269 | + |
| 270 | +import java.util.Arrays; |
| 271 | +import java.util.stream.Stream; |
| 272 | + |
| 273 | +/* |
| 274 | + Stream流中的静态方法concat用于把流组合到一起 |
| 275 | + static <T> Stream<T> concat(Stream(? extends T) a,Stream(? extends T) b) |
| 276 | + */ |
| 277 | +public class Demo08Stream_concat { |
| 278 | + public static void main(String[] args) { |
| 279 | + //定义第一个Stream流 |
| 280 | + Stream<Integer> stream1 = Arrays.asList(1, 2, 3).stream(); |
| 281 | + //定义第二个Stream流 |
| 282 | + Stream<String> stream2 = Arrays.asList("a", "b", "c").stream(); |
| 283 | + //使用Stream接口中的静态方法concat组合上面两个流,然后遍历输出 |
| 284 | + Stream.concat(stream1,stream2).forEach(System.out::println); |
| 285 | + } |
| 286 | +} |
| 287 | +``` |
| 288 | + |
| 289 | +## reduce |
| 290 | + |
| 291 | +reduce方法是通过二元运算对所有元素进行聚合得到一个的流 |
| 292 | + |
| 293 | +使用如下 |
| 294 | + |
| 295 | +```java |
| 296 | +package com.hs_vae.Stream; |
| 297 | + |
| 298 | +import java.util.Arrays; |
| 299 | + |
| 300 | +public class Demo09Stream_reduce { |
| 301 | + public static void main(String[] args) { |
| 302 | + //定义一个存放1,2,3的List集合,转换为流调用reduce方法聚合操作,让元素互相进行相乘,在调用get方法返回该结果 |
| 303 | + Integer integer = Arrays.asList(1, 2, 3).stream().reduce((x, y) -> x * y).get(); |
| 304 | + System.out.println(integer); |
| 305 | + } |
| 306 | +} |
| 307 | +``` |
| 308 | + |
| 309 | +## mapToInt |
| 310 | + |
| 311 | +IntStream mapToInt(ToIntFunction<? super T> mapper) |
| 312 | + |
| 313 | +使用mapToInt方法返回一个IntStream,其中包含将给定函数应用于此流的元素的结果,在使用summaryStatistics方法产生int类型对象 |
| 314 | + |
| 315 | +使用如下 |
| 316 | + |
| 317 | +```java |
| 318 | +package com.hs_vae.Stream; |
| 319 | + |
| 320 | +import java.util.Arrays; |
| 321 | +import java.util.IntSummaryStatistics; |
| 322 | +import java.util.List; |
| 323 | + |
| 324 | +public class Demo10Stream_mapToInt { |
| 325 | + public static void main(String[] args) { |
| 326 | + List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); |
| 327 | + /* |
| 328 | + IntStream mapToInt(ToIntFunction<? super T> mapper) |
| 329 | + 使用mapToInt方法返回一个IntStream,其中包含将给定函数应用于此流的元素的结果,在使用summaryStatistics方法产生int类型对象 |
| 330 | + */ |
| 331 | + IntSummaryStatistics stat = list.stream().mapToInt((x) -> x).summaryStatistics(); |
| 332 | + System.out.println("平均数:"+stat.getAverage()); |
| 333 | + System.out.println("最大值:"+stat.getMax()); |
| 334 | + System.out.println("最小数:"+stat.getMin()); |
| 335 | + System.out.println("总和:"+stat.getSum()); |
| 336 | + } |
| 337 | +} |
| 338 | +``` |
0 commit comments