流的个人理解:
Stream也就是流,他和IO流不一样,他是java8诞生的东西,我对他的理解就是一个更为高级的容器,他可以轻易的对立面存储的数据进行各种各样的操作,比如过滤,转换,迭代等等。
流对集合,数组等进行了进一步的封装,使开发人员更容易的进行操作。
怎样获得流:
//List.stream List<String> stringList = Lists.newArrayList(); Stream<String> stream = stringList.stream(); //Arrays.stream String[] strings = new String[ 2 ]; Stream<String> stream1 = Arrays.stream(strings); //基础类型流 IntStream intStream = IntStream.of( 1 , 2 , 3 ); LongStream longStream = LongStream.of( 1 , 2 , 3 ); DoubleStream doubleStream = DoubleStream.of( 1 , 2 , 3 ); //无限流 Stream.iterate( 0 , i -> i + 1 ); //当前值为上一个值+1,永无止境 Stream.generate(Math::random); //每次获得的值是一个随机数,永无止境 这里提一句,这些方法的底层都是StreamSupport.stream(),他会把List,array封装为spliterator,具体细节可以观看源码。 |
怎样处理流:
中间操作和终端操作介绍:
如果把流看成是水源,水通过管道传输,管道中的各种阀门,可以看成是中间操作,比如过第一个阀门我给他限制排水量,第二个阀门,我往水里加可乐粉,当水离开管道后,把他放入水箱,
是终端操作,这个比喻可能不太恰当,下面写下比较官方的说法。
中间操作:诸如filter或sorted等中间操作会返回另一个流。这让多个操作可以连接起来形成一个查询。
终端操作:终端操作会从流的流水线生成结果。其结果是任何不是流的值,比如List、Integer,甚至void。
中间操作和终端操作的使用:
@Test public void test(){ Stream<Person> stream = allPersonList.stream(); //只留下年龄大于25的人,中间操作 Stream<Person> personStream = stream.filter(person -> person.getAge() > 25 ); //将person流提取出name转换成String流,中间操作 Stream<String> personNameStream = personStream.map(Person::getName); //将流收集起来转换成List,终端操作 List<String> nameList = personNameStream.collect(Collectors.toList()); System.out.println(nameList); } 当然你可能会说这也太复杂了,我不用流也可以简单实现 @Test public void test() { List<String> nameList = Lists.newArrayList(); for (Person person : allPersonList) { if (person.getAge() > 25 ) { nameList.add(person.getName()); } } System.out.println(nameList); } 没错,这样做也很好的实现了,但是你看一下下面的代码 @Test public void test() { //筛选出年龄大于25的人的名字,是不是向读这句话一样简单的读完了这行代码 List<String> nameList = allPersonList.stream().filter(person -> person.getAge() > 25 ).map(Person::getName).collect(Collectors.toList()); System.out.println(nameList); } |
这里还有提一点,Stream的操作属于懒加载,在终端操作执行前,所有的中间操作实际上都没有执行,他们每次都返回一个新的流并且把老的流存入他的成员变量里,这些中间操作形成了一个链表,在执行终端操作时,这些中间操作才会进行真正的操作。