第一个Stream Demo
IDEA里面写Stream有个坑
虽然java文件中没错,但是但编译的时候还是报错了,
Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8
解决方法是:perferences -> Build,Execution, Deployment -> Compiler -> Java Compiler
设置相应Module的 bytecode version即可
public class StreamDemo { public static void main(String[] args) { List<String> list1 = new ArrayList<String>(); list1.add("apple"); list1.add("banana"); list1.add("orange"); list1.add("watermelon"); final Iterator<String> iterator = list1.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } final long count = list1.stream().filter(str -> str.length() > 5).count(); System.out.println("长度大于5的字符串个数为:" + count); } }
终于成功了......
Stream初步
Stream是元素的集合,这点让Stream看起来用些类似Iterator;
可以支持顺序和并行的对原Stream进行汇聚的操作;
大家可以把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如"过滤掉长度大于10的字符串"、"获取每个字符串的首字母"等,具体这些操作如何应用到每个元素上。
图片就是对于Stream例子的一个解析,可以很清楚的看见:原本一条语句被三种颜色的框分割成了三个部分。红色框中的语句是一个Stream的生命开始的地方,负责创建一个Stream实例;绿色框中的语句是赋予Stream灵魂的地方,把一个Stream转换成另外一个Stream,红框的语句生成的是一个包含所有nums变量的Stream,进过绿框的filter方法以后,重新生成了一个过滤掉原nums列表所有null以后的Stream;蓝色框中的语句是丰收的地方,把Stream的里面包含的内容按照某种算法来汇聚成一个值,例子中是获取Stream中包含的元素个数。
在此我们总结一下使用Stream的基本步骤:
创建Stream;
转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(**可以有多次转换**);
对Stream进行聚合(Reduce)操作,获取想要的结果;
最常用的创建Stream有两种途径:
通过Stream接口的静态工厂方法(注意:Java8里接口可以带静态方法);
通过Collection接口的默认方法(默认方法:Default method,也是Java8中的一个新特性,就是接口中的一个带有实现的方法,后续文章会有介绍)–stream(),把一个Collection对象转换成Stream
使用Stream静态方法来创建Stream
1. of方法:有两个overload方法,一个接受变长参数,一个接口单一值
Stream<Integer> integerStream = Stream.of(1, 2, 3, 5);
Stream<String> stringStream = Stream.of("hehe");
2. generator方法:生成一个无限长度的Stream,其元素的生成是通过给定的Supplier(这个接口可以看成一个对象的工厂,每次调用返回一个给定类型的对象)
Stream.generate(new Supplier<Double>() { @Override public Double get() { return Math.random(); } }); Stream.generate(() -> Math.random()); Stream.generate(Math::random);
三条语句的作用都是一样的,只是使用了lambda表达式和方法引用的语法来简化代码。每条语句其实都是生成一个无限长度的Stream,其中值是随机的。这个无限长度Stream是懒加载,一般这种无限长度的Stream都会配合Stream的limit()方法来用。
3. iterate方法:也是生成无限长度的Stream,和generator不同的是,其元素的生成是重复对给定的种子值(seed)调用用户指定函数来生成的。其中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环
Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);
这段代码就是先获取一个无限长度的正整数集合的Stream,然后取出前10个打印。千万记住使用limit方法,不然会无限打印下去。
2.2 通过Collection子类获取Stream
这个在本文的第一个例子中就展示了从List对象获取其对应的Stream对象,如果查看Java doc就可以发现Collection接口有一个stream方法,所以其所有子类都都可以获取对应的Stream对象。
public interface Collection<E> extends Iterable<E> { //其他方法省略 default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } }