java8的流操作

Java8引入了流-Stream API,

1什么是流

:java API的一个新成员,使用这个api可以简明高效的处理数据集,可以理解成遍历数据集的内部迭代器。

      简明:使用声明式方查询语句来表达,无需临时编写实现代码。

      高效:可以透明的进行并行处理。

使用旧例子: 对菜单中的菜品进行过滤,找出符合条件的菜肴

/**
 * 菜品
 */
@Data
@AllArgsConstructor
public class Dish { 
    private final String name;         //菜名
    private final boolean vegetarian;  //是否为素菜
    private int calories;     //菜的热量
    private final Type type;  //菜的类型
 
    public enum Type{ MEAT,FISH,OTHER}
}

List menuNames=menu.stream()            //1:从menu获取流
                .filter(d->d.getCalories()>300)     //2:筛选出高热量的菜品
                .map(Dish::getName)            //3:使用映射获取菜品名称
                .limit(3)                  //4:截短只取前三个符合条件的结果
                .collect(Collectors.toList());  //5:结束流操作,将流保存到另外一个List中

使用上面的一句代码就可以实现这个复杂的操作。

2 认识流

   源:流的数据来源,比如集合、数组或输入输出资源(有序集合生成的流元素顺序和原有集合一致)

  元素序列:流就像集合一样提供了接口,是一组特定元素类型的有序值。(集合侧重数据存储,流侧重数据计算)

  流处理操作:流的数据处理功能支持类似于数据库的声明式操作,以及函数式编程的常用操作,如filter,map,reduce,find,match,sort等,即可顺序执行,也可并行执行。

  流水线:多个流操作链接起来,就形成了一个流水线,可以看做是是一种类似于数据库式的查询式处理。

  内部迭代:流的迭代操作是在背后操作的,而非像迭代器那样进行显示迭代。

3 流的特点

3.1流与集合的区别

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

流 则是概念上固定的数据结构,不能删除或添加元素,元素按需计算;是一种“生产者-消费者”的关系,就像一个延迟创建的集合,只有消费者要求时才会计算值。

3.2 使用流的代码具有以下特点

    声明性:使用声明式方查询语句,简洁易懂。

    可复合Stream API方法可灵活结合使用。

    可并行内部对并行做了处理,使用者可以不用关心并行

除此之外,还有其他特点:

    流只能遍历一次:流和迭代器一样,只能遍历一次,一旦遍历完,这个流就被消费掉了,除非你再从原始数据重新获取一个流。

    流使用内部迭代:Stream ApI帮你把迭代做了,并将流值保存在某个地方,你只要给出函数说要干什么就行了。

 

Java8引入流的理由:Stream库的内部迭代可以自动选择符合硬件的数据表示和并行实现

 

4 流操作

还是上面的例子:  menu.stream().filter(d->d.getCalories()>300).map(Dish::getName).limit(3).collect(Collectors.toList());

 

所以,使用流包括了三部分:

        一个数据源:比如集合。

        一个中间操作链:形成一条流的流水线。

        一个终端操作:执行流水线,能生成结果。

其中,诸如filter,map,limit这样的操作都叫做中间操作,它们都会返回另外一个流给其他中断操作使用,所以中间操作方法是可以联合起来使用。除非它们遇到终端操作,一次性处理完所有的流。

终端操作则会从流水线上生成结果。生成非流值,比如List,Integer,void

常用的流操作

    filter:谓词筛选,接受一个谓词(返回boolean的函数,如:.filter(Dish::isVegetarian))

    distinct:筛选掉重复元素(.distinct())

    limit:截短流(.limit(n)),方法返回不超过n个元素

    skip:跳过元素(.skip(n)),扔掉钱n个元素

    map:映射(.map(func)),,接受一个函数,该该函将每个元素映射成另外一个元素。

    flatMap:流的扁平化,将流中的所有块,映射成一个流的内容,拆分了流中的块。

短路操作:一旦匹配中,就停止计算流,返回boolean结果。

    anyMatch:流中是否有一个元素能匹配给定的谓词(.anyMatch(Dish::isVegetarian))

    allMatch:它会判断流中的元素是否都能匹配中谓词,例子同上

    noneMatch:它会确保每个元素无法匹配中,一旦有匹配中的就返回false

上面的都是短路操作,limit也是短路操作。

查找元素

    .findAny()

    .findFirst()

归约:将流中所有元素结合起来得到一个值(流规约为一个值)

    numberList.reduce(0,(a,b)->a+b)

你可能感兴趣的:(【Java】)