Java 8新特性之Stream流

Posted 笨笨的二黄子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 8新特性之Stream流相关的知识,希望对你有一定的参考价值。

Java8新特性之Stream流

什么是Stream流

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。 是一个来自数据源的元素队列并支持聚合操作

  1. 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  2. 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  3. 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

Stream特点

  • 无存储。Stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
  • 为函数式编程而生。对Stream的任何修改都不会修改背后的数据源,比如对Stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新Stream。
  • 惰式执行。Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
  • 可消费性。Stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

Stream流操作

1: 创建Stream

主要负责新建一个Stream流,或者基于现有的数组、List、Set、Map等集合类型对象创建出新的Stream流。

API 功能说明
stream() 创建出一个新的stream串行流对象
parallelStream() 创建出一个可并行执行的stream流对象
Stream.of() 通过给定的一系列元素创建一个新的Stream串行流对象

示例

    /**
     * 通过集合生成,应用中最常用的一种
     */
    List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
    Stream<Integer> stream1 = integerList.stream();

    /**
     * 通过数组生成
     */
    int[] intArr = new int[]1, 2, 3, 4, 5;
    IntStream stream2 = Arrays.stream(intArr);


    /**
     * 创建并行流对象
     */
    Stream<Integer> promotionStream = integerList.parallelStream();

2: 中间管道

​ 负责对Stream进行处理操作,并返回一个新的Stream对象,中间管道操作可以进行叠加

API 功能说明
filter() 按照条件过滤符合要求的元素, 返回新的stream流
map() 将已有元素转换为另一个对象类型,一对一逻辑,返回新的stream流
flatMap() 将已有元素转换为另一个对象类型,一对多逻辑,即原来一个元素对象可能会转换为1个或者多个新类型的元素,返回新的stream流
limit() 仅保留集合前面指定个数的元素,返回新的stream流。limit的参数值必须>=0,否则将会抛出异常
skip() 跳过集合前面指定个数的元素,返回新的stream流。skip的参数值必须>=0,否则将会抛出异常
concat() 将两个流的数据合并起来为1个新的流,返回新的stream流
distinct() 对Stream中所有元素进行去重,返回新的stream流
sorted() 对stream中所有的元素按照指定规则进行排序,返回新的stream流
peek() 对stream流中的每个元素进行逐个遍历处理,返回处理后的stream流

示例:

filter()

    /**
    * filter筛选
    * 通过使用filter方法进行条件筛选,filter的方法参数为一个条件
    */
    List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
    Stream<Integer> stream = integerList.stream().filter(i -> i > 3);

map()

主要用于List 循环获取Entity的属性值

    /**
    * map流映射(所谓流映射就是将接受的元素映射成另外一个元素)
    */
    List<String> stringList = Arrays.asList("str1", "str2", "str3", "str5");
    Stream<Integer> streams = stringList.stream().map(String::hashCode);

flatMap()

将已有元素转换为另一个对象类型,一对多逻辑

    /**
    * flatMap流转换(将一个流中的每个值都转换为另一个流)
    */
    List<String> wordList = Arrays.asList("Hello", "World");

    List<String> strList = wordList.stream()
    .map(w -> w.split("r"))
    .flatMap(Arrays::stream)
    .distinct()
    .collect(Collectors.toList());

limit()

    /**
    * limit返回指定流个数
    * 通过limit方法指定返回流的个数,limit的参数值必须>=0,否则将会抛出异常
    */
    List<String> wordList = Arrays.asList("Hello", "World","!");

    Stream<String> limitStream = wordList.stream().limit(1);

skip()

    /**
    * skip跳过流中的元素
    * 通过skip方法跳过流中的元素,例子中打印出来的数据: World,! 。skip的参数值必须>=0,否则将会抛出异常
    */
    List<String> wordList = Arrays.asList("Hello", "World","!");

    Stream<String> limitStream = wordList.stream().skip(1);

concat()

    Stream<String> streamOne = Stream.of("Hello");
    Stream<String> streamTwo = Stream.of("World");
    Stream<String> concatStream = Stream.concat(streamOne, streamTwo);

distinct()

    /**
    * distinct主要用来去重,以下代码片段使用 distinct 对元素进行去重
    */
    List<String> wordList = Arrays.asList("Hello", "World","!","Hello","!");

    Stream<String> limitStream = wordList.stream().distinct();

sorted()

        /**
         * sorted对流进行排序
         * sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法进行排序
         */
        List<Integer> integerList = Arrays.asList(1, 3,2,10,7);
        Stream<Integer> sortedStream = integerList.stream().sorted();

        /**
         * 通过比较器比较
         */
        List<String> wordList = Arrays.asList("Hello", "World","!","Hello","!");
        wordList.stream().sorted(((str1, str2) -> 
            if (str1.length()> str2.length()) 
                return -1;
             else 
                return 1;
            
        ));

peek()

        /**
         * peek()属于中间方法,没有结束
         * peek只能作为管道中途的一个处理步骤,而没法直接执行得到结果,其后面必须还要有其它终止操作的时候才会被执行
         */
        List<String> wordList = Arrays.asList("Hello World!");
        //没有输出
        wordList.stream().peek(sentence -> System.out.println(sentence));
        //输出结果
        wordList.stream().peek(sentence -> System.out.println(sentence)).count();

3: 终止管道

​ 通过终止管道操作之后,Stream流将会结束,最后可能会执行某些逻辑处理,或者是按照要求返回某些执行后的结果数据

API 功能说明
count() 返回stream处理后最终的元素个数
max() 返回stream处理后的元素最大值
min() 返回stream处理后的元素最小值
findFirst() 找到第一个符合条件的元素时则终止流处理
findAny() 找到任何一个符合条件的元素时则退出流处理,这个对于串行流时与findFirst相同,对于并行流时比较高效,任何分片中找到都会终止后续计算逻辑
anyMatch() 返回一个boolean值,类似于isContains(),用于判断是否有符合条件的元素
allMatch() 返回一个boolean值,用于判断是否所有元素都符合条件
noneMatch() 返回一个boolean值, 用于判断是否所有元素都不符合条件
collect() 将流转换为指定的类型,通过Collectors进行指定
toArray() 将流转换为数组
iterator() 将流转换为Iterator对象
foreach() 无返回值,对元素进行逐个遍历,然后执行给定的处理逻辑

count()

count用来统计流中的元素个数。

        /**
         * 统计流中元素个数
         * 通过使用count方法统计出流中元素个数
         */
        List<String> wordList = Arrays.asList("Hello","World","!!");
        long count = wordList.stream().count();

max()/min()

获取流中最小最大值

        List<Integer> integerList = Arrays.asList(100,111,22,3,343);
        Optional<Integer> min = integerList.stream().min(Integer::compareTo);
        Optional<Integer> max = integerList.stream().max(Integer::compareTo);

findFirst()

查找大于100的第一个值

		  /**
         * 查询列表中大于100的数值
         */
        List<Integer> integerList = Arrays.asList(100,111,22,3,343);
        Optional<Integer> result = integerList.stream().filter(v -> v > 100).findFirst();

findAny()

找到任何一个符合条件的元素时则退出流处理

        List<Integer> integerList = Arrays.asList(100,343,22,3,111);
        Optional<Integer> result = integerList.stream().filter(v -> v > 100).findAny();
        System.out.println(result.get());

anyMatch()

		  /**
         * 查询列表中是否包含111的字符串
         */
        List<String> integerList = Arrays.asList("100", "343","22","3","111");
        boolean b = integerList.stream().anyMatch("111"::equals);

allMatch()

这个和anyMatch() 的类似,列表里面的元素都要匹配上。

noneMatch()

这个和anyMatch() 的类似,列表里面的元素都不能匹配上。

剩下的都是一些比较简单的,这里不在进行举例了。

优势和劣势

相对于foreach的方式,Stream有很多优势:

  1. 代码简洁,逻辑清洗
  2. 函数式接口,延迟执行的特性,中间管道操作不管有多少步骤都不会立即执行,只有遇到终止操作的时候才会开始执行,可以避免一些中间不必要的操作消耗
  3. 并行流场景效率会比迭代器逐个循环更高

劣势:

  1. 代码调试不是很方便
  2. 开发者需要去适应这种模式

以上就是本篇文章的所有内容,请大家多多指教。

Java While 循环


章节


循环

只要满足指定的条件,循环会反复执行某个代码块。

Java While 循环

只要条件为真,while循环语句会循环执行一个代码块:

语法

while (条件) {
  // 要执行的代码块
}

在下面的例子中,只要变量(i)小于5,循环中的代码就会反复运行:

示例

int i = 0;
while (i < 5) {
  System.out.println(i);
  i++;
}

注意: 不要忘记给变量i递增,否则循环将永远不会结束!

Do/While

do/while循环是while循环的变体。此循环将先执行一次代码块,然后再检查条件,只要条件为真,循环将继续。

语法

do {
  // 要执行的代码块
}
while (条件);

下面的示例使用do/while循环,循环将至少执行一次,即使条件是假的。因为会先执行一次代码块,然后再检查条件:

示例

int i = 0;
do {
  System.out.println(i);
  i++;
}
while (i < 5);

注意: 不要忘记给变量i递增,否则循环将永远不会结束!

以上是关于Java 8新特性之Stream流的主要内容,如果未能解决你的问题,请参考以下文章

乐字节-Java8新特性-接口默认方法之Stream流(下)

Java 8新特性之 并行和并行数组(八恶人-8)

Java函数式编程之Stream流编程

java8新特性

java8新特性之Stream

Java8 新特性之集合操作Stream