最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java Stream的基本概念以及创建方法代码解析
时间:2020-08-28 编辑:袖梨 来源:一聚教程网
本篇文章小编给大家分享一下Java Stream的基本概念以及创建方法代码解析,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
Stream 与 Collection 的区别
1.用途与关注点不同
Collection 主要关注于对象的存储方面,通过使用List、Map、Set等等数据结构,让数据被更好的组织起来,以便于使用。而 Stream 则关注于对象的操作方面,包含reduce、map、filter等等实用的操作。
2.流是懒搜索(Laziness-seeking)的
先看一个例子,考虑一下代码:
Random random = new Random(29); random.ints() .filter(v -> v > 5 && v < 31) .limit(3) .forEach(System.out::println); // output: // 21 // 22 // 28
代码首先创建了一个随机整数流,然后过滤得到其中在(5, 31)范围内的数,最终得到其中的3个数并输出,这里创建的流就是3中所说的无限流,而流在执行的过程中一旦得到一个满足条件的整数就会加到结果序列中,并且开始进行下一轮的搜索,直到找到3个满足的整数为止。流只会完成所给任务(找到3个满足指定范围的整数并输出),不会有额外的操作。
3.流的大小可以是无限的
尽管 Collection 的数据量也可以动态扩展改变,但由于计算机内存是有限的,所以其数据量大小始终可以看成只能为有限的大小。但 Stream 则不同,由于流是懒加载的,所以当使用limit类似的短路操作时,就可以利用特性2的原因去接收一个无限流。
4.流操作不存在副作用
和 Collection 中的某些操作,例如remove会删除集合中的元素不同,流不会修改生成流的原有集合中的数据,例如使用filter时,会产生一个经过元素过滤后的新流,而不会修改原集合中的数据。
5.流属于消耗品(Consumable)
不同与 Collection 没有访问次数与使用的限制,一个流在其生命周期中只能被执行一次,当执行了终端操作(terminal operation,在之后的文章中会具体介绍)后,即使没有将流关闭,例如上述代码中的forEach,也无法再次访问了(类似迭代器),如下代码所示,想要再操作,必须重新创建一个流。
IntStream stream = new Random(29).ints(); stream.filter(v -> v > 5 && v < 31) .limit(3) .forEach(System.out::println); // 当执行了终端操作后再使用,就会出现一下异常提示信息 // java.lang.IllegalStateException: stream has already been operated upon or closed stream.forEach(System.out::println);
创建流
流可以通过很多种方式被创建,下面进行一一介绍:
1.Collection 家族创建的方式
对于实现了Collection 接口的类,都可以通过stream()和parallelStream()创建对应流,如下代码所示:
Listlist = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); // 创建一个普通的流 Stream stream = list.stream(); // 创建一个并行流 Stream parallelStream = list.parallelStream();
2.数组家族创建的方式
对于数组类型的元素,都可以使用Arrays类的stream()创建对应的流,如果想获得并行流则需要使用parallel()方法,如下所示:
IntStream stream = Arrays.stream(new int[]{1, 2, 3}); // 生成流对应的并行流 IntStream parallelStream = stream.parallel();
3.Stream家族的工厂方法
通过工厂方法来创建流的方式比较多,可以通过empty、of、concat、generate、iterate、range、rangeClosed以及builder等方法创建流,下面就通过代码样例来一一介绍:
// 产生一个不包含任何元素的流 Stream
4.IO/NIO家族中的方法
除了两种获取lines生成的流外,其它几种方式都很少使用,这一部分了解即可。
try { String dir = System.getProperty("user.dir"); // 以下两种方法均是获取文件中行数据组成的流 Streamstream1 = new BufferedReader(new FileReader(dir + "\demo.txt")).lines(); Stream stream2 = Files.lines(Paths.get(dir + "\demo.txt")); // 获取指定路径下所有文件/文件夹的路径组成的流 Stream stream3 = Files.list(Paths.get("d:\temp")); // 获取指定路径下以及指定最深文件层级内(在这里为2)且满足函数条件的所有文件/文件夹的路径组成的流 Stream stream4 = Files.find( Paths.get("d:\temp"), 1, (path, basicFileAttributes) -> path.isAbsolute()); // 获取指定路径下以及指定最深文件层级内(在这里为2)所有文件/文件夹的路径组成的流 Stream stream5 = Files.walk(Paths.get("d:\temp"), 2); } catch (IOException e) { e.printStackTrace(); }
5.Random 获取流的方式
由于直接使用 Random 类生成随机数无限流,均为基本数据类型组成的流,因此通常还需要使用boxed方法进行装箱(以前凡是生成的为IntStream,DoubleStream,LongStream均同此),以便可以使用更加丰富的特性。
Random random = new Random(); // 以下三种方式得到的均是随机数组成的<无限流> IntStream stream1 = random.ints(); DoubleStream stream2 = random.doubles(); LongStream stream3 = random.longs(); StreamboxedStream = stream1.boxed();
下面就先举一个具体的实用的例子,在之后的文章中会详细介绍一些实用操作,这里可以先做了解:
// 对数组元素进行倒序排序 // 如果不进行装箱(boxed)处理,则只能使用默认的升序排序方法 // 通过装箱,则可以通过自定义比较器,实现更加多样的排序 int[] arr = {1, 5, 4, 6, 3, 9, 4, 5, 6, 4}; int[] reverseArr = Arrays.stream(arr) .boxed() .sorted(Comparator.reverseOrder()) .mapToInt(Integer::valueOf) .toArray(); // output: [9, 6, 6, 5, 5, 4, 4, 4, 3, 1] System.out.println(Arrays.toString(reverseArr));
6.其它可以生成流的类
除了以上介绍的几个主要可以生成流的类之外,还有一些其它不太常见的可以流的类,下面是部分代码展示:
String s = "1,2,3,4,5,6,7"; // 由分割后的字符串组成的流 // 在这里就是"1", "2", "3", "4", "5", "6", "7"组成的流 Streamstream1 = Pattern.compile(",").splitAsStream(s); BitSet bitSet = new BitSet(); for (int i = 0; i < 10; i++) { if (i % 2 == 0) { bitSet.set(i); } } // 由 bitset 中被设置为 true 的位下标所组成的流 // 在这里就是0, 2, 4, 6, 8 IntStream stream2 = bitSet.stream(); try { String dir = System.getProperty("user.dir"); JarFile jarFile = new JarFile(dir + "\demo.jar"); // 由指定 jar 包中所有文件及文件夹的 JarEntry 对象所组形成的流 Stream stream3 = jarFile.stream(); } catch (IOException e) { e.printStackTrace(); }
此外还可以通过 StreamSupport工具类进行产生和操作流,由于本文包括之后的文章主要是为了入门和先简单上手,所以这里不做详细讨论,感兴趣的可以自己进行查阅资料。
相关文章
- SpringBoot自定义bean绑定解析 10-24
- Javaweb工程运行报错HTTP Status 404解决教程 10-20
- JAVA获取jvm和操作系统相关信息方法 10-20
- BeanFactory和FactoryBean的区别讲解 10-20
- 微信小程序的宿主环境实现教程 10-10
- dispatchEvent解决重叠元素响应事件教程 10-10