第4章 引入流

流是什么

流是JavaAPI的新成员,以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现),流还可以并行处理,无需写任何多线程的代码。

从菜单列表中筛选热量少于400的菜,然后对这些菜按照热量进行升序排列,最后获得这些菜单的名称列表。

没有使用流,普通处理:

//筛选热量小于400的菜
List lowCaloricDishes = new ArrayList<>();
for (Dish dish : menus){
    if (dish.getCalories() < 400){
        lowCaloricDishes.add(dish);
    }
}

//热量小于400的菜,根据热量进行排序
Collections.sort(lowCaloricDishes, new Comparator(){

    @Override
    public int compare(Dish o1, Dish o2) {
        return Integer.compare(o1.getCalories(), o2.getCalories());
    }
});

//热量小于400的菜,获得菜名单列表
List lowCaloricDishesName = new ArrayList<>();
for (Dish dish : lowCaloricDishes){
    lowCaloricDishesName.add(dish.getName());
}

使用流进行处理:

List lowCaloricDishesName2 = menus.stream()
        .filter(d -> d.getCalories() < 400)
        .sorted(Comparator.comparing(Dish::getCalories))
        .map(Dish::getName)
        .collect(toList());

使用流多线程处理:

List lowCaloricDishesName2 = menus.parallelStream()
        .filter(d -> d.getCalories() < 400)
        .sorted(Comparator.comparing(Dish::getCalories))
        .map(Dish::getName)
        .collect(toList());


流操作处理链

使用StreamAPI可以写出这样的代码:

流简介

流到底是什么?简短的定义就是“从支持数据处理操作的源生成元素序列”


  1. filter:接受一个Lambda,从流中排除某些元素。在本例中选择热量大于300的卡路里。
  2. map:接受一个Lambda,将元素转换成其他形式或提取信息。在本例中提取菜单的名称。
  3. limit:截断流,使其元素不超过给定数量。
  4. collect:将流转换成其他形式。

流与集合

流与集合的差异在于什么时候进行计算。

集合是一个内存中的数据结构,它包含数据结构中目前所有的值,集合中的每个元素都得先计算出来才能添加到集合中。

流则是在概念上固定的数据结构(不能添加和删除元素),其元素是按需计算,用户从流中提取需要的值,而这些值----在用户看不见得地方,只会按需生成,这是一种生产者-消费者得关系,从另外一个角度来说,流就像是一个延迟创建得集合,只有在消费者要求得时候才会计算值。

只能遍历一次

流只能遍历一次,遍历完后,我们就说这个流已经被消费掉了。


外包迭代与内部迭代

使用Collection接口需要用户去做迭代(比如for-each),这称为外部迭代,相反,Stream库使用内部迭代-----他帮你把迭代做了,还把得到得流值存在了某个地方,你只要给出一个函数说要干什么就可以。

外部迭代:


内部迭代:



流操作

流操作有两大类,可以连接起来的操作称为中间操作,关闭流的操作称为终端操作。


1、中间操作

filter或sorted等中间操作会返回另一个流,让多个操作可以连接起来形成一个查询。除非流水线上触发一个终端操作,否则中间操作不会执行任何处理---他很懒。因为中间操作一般都可以合并起来,在终端操作时一次性全部处理。

操作

类型

返回类型

操作参数

函数描述符

filter

中间

Stream

Predicate

T -> boolean

map

中间

Stream

Function

T -> R

limit

中间

Stream



sorted

中间

Stream

Comparator

(T,T) -> int

distinct

中间

Stream



2、终端操作

终端操作会从流的流水线生成结果,其结果不时流,而是List、Integer、甚至void。

操作

类型

返回类型

目的

forEach

终端

void

消费流中的每个元素并对其应用Lambda

count

终端

long

返回流中元素的个数

collect

终端

generic

把流归约成一个集合,比如List、Map,甚至是Integer

使用流

使用流一般包括三件事:

展开阅读全文

页面更新:2024-03-12

标签:升序   目的   数据源   终端   流水线   热量   菜单   元素   类型   操作

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top