第四章:引入流

流是什么

定义:从支持数据处理的操作的源生成的元素序列
流是javaAPI的新成员,他让你以生命的方式处理数据集合(简要理解成高级迭代器)。可以透明的并行处理
来对比一下两段代码都是用来返回热量的菜肴名称,并按照卡路里排序

java8 之前

        List lowCaloricDishes = new ArrayList<>();
        for (Dish d:lowCaloricDishes){
            if (d.getCalories() < 400){
                lowCaloricDishes.add(d);
            }
        }
        Collections.sort(lowCaloricDishes, new Comparator() {
            @Override
            public int compare(Dish o1, Dish o2) {
                return Integer.compare(o1.getCalories(),o2.getCalories());
            }
        });
        List lowCaloricDishesName = new ArrayList<>();
        for (Dish d:lowCaloricDishes){
            lowCaloricDishesName.add(d.getName());
        }

java8非并行

        List lowCaloricDishesName = 
                menu.stream()
                        .filter(dish -> dish.getCalories() < 400)
                        .sorted(Comparator.comparing(Dish::getCalories))
                        .map(Dish::getName)
                        .collect(Collectors.toList());

java8并行

        List lowCaloricDishesName =
                menu.parallelStream()
                        .filter(dish -> dish.getCalories() < 400)
                        .sorted(Comparator.comparing(Dish::getCalories))
                        .map(Dish::getName)
                        .collect(Collectors.toList());

java8中的Stream API可以让我呢写出如下代码
声明性——更简洁,更紧凑
可复用性——更灵活
可并性——性能更好

流简介

流的特点
1,流水线——很多流水线合成一个大流水线
2,内部迭代

分析如下代码

        List threeHighCaloricDishNames = menu.stream()
                .filter(dish -> dish.getCalories() > 300)
                .map(Dish::getName)
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(threeHighCaloricDishNames);
流操作顺序(筛选菜单,找出两个高热量菜肴的名称).png

流和集合

1,集合是数据结构,它以特定的时间/空间复杂度存储访问元素
流是在于表达计算
2,什么时间进程计算
集合是一个内存中的数据结构,他包含数据结构中目前所有的值——集合中的每个元素都先算出来才能到集合中,集合中的每个元素都是放在内存里的(元素都要先算出来才能成为集合的一部分)
流是概念上的固定数据结构(你不能添加或删除元素),其元素是按需计算的,像是一个延迟创建的集合,集合是急切创建
3,哲学中的集合和流
集合为空间上的一组值,在时间点上全体存在
流为时间上的一组值

只能遍历一次

与迭代器类似,流只能遍历一次

        List title = Arrays.asList("Java8","In","Action");
        Stream s = title.stream();
        s.forEach(System.out::println);
        s.forEach(System.out::println);//这里会报异常

这段代码会爆异常,异常如下


image.png

外部迭代与内部迭代

for-each循环外部迭代

        for (Dish d:lowCaloricDishes){
            lowCaloricDishesName.add(d.getName());
        }

while迭代器外部迭代

        List title = Arrays.asList("Java8","In","Action");
        Iterator iterator = title.iterator();
        while (iterator.hasNext()){
            String s = iterator.next();
        }

流内部迭代

        List names = menu.stream()
                .map(Dish::getName)
                .collect(Collectors.toList());

内部迭代为什么比外部迭代好?
举个例子,让小孩子收拾玩具
外部迭代,要停的去询问每个具体的玩具收拾完没,要自己管理并行
内部迭代,不需要去询问每个记得玩具收拾完没,并且不需要关心孩子是如何收拾玩具的,这样有利于底层优化(比如是串行的还是并行的)

流操作

        List threeHighCaloricDishNames = menu.stream()
                .filter(dish -> dish.getCalories() > 300)
                .map(Dish::getName)
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(threeHighCaloricDishNames);

filter,map,limit可以连成一条流水线
collection触发流水线执行并关闭它

中间操作

除非触发终端操作,否则中间操作不会执行任何处理(中间操作一般都是可以合并起来的,在终端操作时一次性全部处理)
操作符
filter
map
limit
sorted
distinct

终端操作

从流水线生成结果。其结果是任何不是流的值(void也是一种结果)
操作符
forEach
count
collect

 menu.stream().forEach(System.out::println);

使用流

流使用包括三件事
1,一个数据源
2,中间操作链
3,终端操作

你可能感兴趣的:(第四章:引入流)