简介:
Stream是Jdk1.8中的一大亮点,支持顺序和并行聚合操作的一系列元素,为了执行计算,流operations被组合成流管道 。 流管线由源(其可以是阵列,集合,生成函数,I / O通道等)组成,零个或多个中间操作 (其将流转换成另一个流,例如
filter(Predicate)
)以及终端操作 (产生结果或副作用,如count()
或forEach(Consumer)
Stream 与 集合的不同:
- 没有存储。 流不是存储元素的数据结构; 相反,它通过计算操作的流水线传送诸如数据结构,阵列,生成器功能或I / O通道的源的元件。
- 功能性质。 流上的操作产生结果,但不会修改其来源。 例如,过滤从
Stream
获得的Stream会生成新的Stream
而不需要过滤的元素,而不是从源集合中删除元素。- 懒惰寻求。 许多流操作(如过滤,映射或重复删除)可以懒惰地实现,从而暴露优化的机会。 例如,“找到具有三个连续元音的第一个
String
”不需要检查所有的输入字符串。 流操作分为中间(Stream
生产)操作和终端(价值或副作用生成)操作。 中级操作总是懒惰。- 可能无限。 虽然集合的大小有限,但流不需要。 诸如
limit(n)
或findFirst()之类的limit(n)
findFirst()
可以允许无限流上的计算在有限的时间内完成。- 消耗品流的元素只能在流的一生中访问一次。 像
Iterator
一样 ,必须生成一个新流来重新访问源的相同元素。
Stream获取:
- 从
Collection
通过stream()
和parallelStream()
方法;- 从数组通过
Arrays.stream(Object[])
;- 从流类静态工厂的方法,如
Stream.of(Object[])
,IntStream.range(int, int)
或Stream.iterate(Object, UnaryOperator)
;- 文件的行可以从
BufferedReader.lines()
获取 ;- 文件路径的流可以从
Files
中的方法获得;- 随机数流可以从
Random.ints()
获得;- JDK中其它的数据流的方法,包括
BitSet.stream()
,Pattern.splitAsStream(java.lang.CharSequence)
和JarFile.stream()
。
//1.定义Collection
List<String> list = new ArrayList<>();
//获取一个串行流
Stream<String> stream = list.stream();
//获取一个并行流-底层是forkJoin实现
Stream<String> stringStream = list.parallelStream();
//2. 使用Arrays 中的 stream() 方法,将数组转成流
String[] array = new String[5];
Stream<String> stream = Arrays.stream(array);
//3.流类静态工厂的方法
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);//1 2 3 4 5 6
Stream<Integer> stream = Stream.iterate(0, (x) -> x + 2).limit(6);// 0 2 4 6 8 10
Stream<Double> stream = Stream.generate(Math::random).limit(2);//随机的2个数字
//4.使用 BufferedReader.lines() 方法,从文件中将每行内容转成流
BufferedReader reader = new BufferedReader(new FileReader("D:\\milla_stream.txt"));
Stream<String> lineStream = reader.lines();
//5.文件路径的流可以从Files中的方法获得
Stream<Path> stream = Files.list(Paths.get("D:\\"));
//6.随机数流可以从Random.ints()获得;
IntStream ints = new Random().ints();//是Stream的子类
//7. 其他类中的方法
IntStream stream1 = new BitSet().stream();//是Stream的子类
Pattern pattern = Pattern.compile(",");
Stream<String> text = pattern.splitAsStream("mila,love");
Stream<JarEntry> stream2 = new JarFile("D:\\milla.jar").stream();
Stream常用的方法解析:
- map: - 接收函数中的参数,根据业务将它变成一个新的元素,形成一个新的集合
- sorted() - 返回由此流的元素组成的流,根据自然顺序排序 默认升序 降序 .reversed(),形成一个新的集合
- filter(); - 过滤,指定过滤条件,形成一个新的集合
- count - 返回流中元素的总个数
- max - 返回流中元素最大值
- findAny - 返回流中的任意元素
- ......
@Test
void testStream() {
Stu du = new Stu("du", 19, "开发");
Stu wang = new Stu("wang", 10, "开发");
Stu li = new Stu("li", 20, "测试");
Stu lu = new Stu("lu", 20, "开发");
List<Stu> list = Arrays.asList(du, wang, li,lu);
//todo map: 获取所有学生的姓名
List<String> stuNameList = list.stream().map(Stu::getName).collect(Collectors.toList());
//todo sorted: 根据年龄进行排序 默认升序
List<Stu> sortByAge = list.stream().sorted(Comparator.comparing(Stu::getAge)).collect(Collectors.toList()); //升序
List<Stu> sortByAgeDesc = list.stream().sorted(Comparator.comparing(Stu::getAge).reversed()).collect(Collectors.toList());//降序
//todo filter: 年龄大于18的
List<Stu> ageThan18 = list.stream().filter(stu -> stu.getAge() > 18).collect(Collectors.toList());
//todo 获取年龄最大的学生
Stu maxAgeStu = list.stream().max(Comparator.comparing(Stu::getAge)).get();
//todo 按照部门分组 map的key为部门名 value为分组的学生集合
Map<String, List<Stu>> groupByDepName = list.stream().collect(Collectors.groupingBy(Stu::getDepName));
//todo 按部门分组求个数
Map<String, Long> map = list.stream().collect(Collectors.groupingBy(Stu::getDepName, Collectors.counting()));
}