千家信息网

java8的Stream特性是什么

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容介绍了"java8的Stream特性是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!ja
千家信息网最后更新 2026年10月31日java8的Stream特性是什么

本篇内容介绍了"java8的Stream特性是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行stream()执行或者并行parallelStream()执行。

一、简介

java8新添加了一个特性:流Stream。Stream让开发者能够以一种声明的方式处理数据源(集合、数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation)和大批量数据操作 (bulk data operation)。

Stream API将处理的数据源看做一种Stream(流),Stream(流)在Pipeline(管道)中传输和运算,支持的运算包含筛选、排序、聚合等,当到达终点后便得到最终的处理结果。

几个关键概念:

  1. 元素 Stream是一个来自数据源的元素队列,Stream本身并不存储元素。

  2. 数据源(即Stream的来源)包含集合、数组、I/O channel、generator(发生器)等。

  3. 聚合操作 类似SQL中的filter、map、find、match、sorted等操作

  4. 管道运算 Stream在Pipeline中运算后返回Stream对象本身,这样多个操作串联成一个Pipeline,并形成fluent风格的代码。这种方式可以优化操作,如延迟执行(laziness)和短路( short-circuiting)。

  5. 内部迭代 不同于java8以前对集合的遍历方式(外部迭代),Stream API采用访问者模式(Visitor)实现了内部迭代。

  6. 并行运算 Stream API支持串行(stream() )或并行(parallelStream() )的两种操作方式。

Stream API的特点:

  1. Stream API的使用和同样是java8新特性的 lambda表达式 密不可分,可以大大提高编码效率和代码可读性。

  2. Stream API提供串行和并行两种操作,其中并行操作能发挥多核处理器的优势,使用fork/join的方式进行并行操作以提高运行速度。

  3. Stream API进行并行操作无需编写多线程代码即可写出高效的并发程序,且通常可避免多线程代码出错的问题。

二、简单示例

我们来看一个简单的示例,统计整数数组中正数的个数:

  1. 在java8之前:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);                long count = 0;                for(Integer number: numbers)        {            if(number > 0)            {                count++;            }        }                System.out.println("Positive count: " + count);    }
  1. 在java8之后:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);              long count = numbers.parallelStream().filter(i -> i>0).count();                System.out.println("Positive count: " + count);    }

可以看到,上例中,使用filter()方法对数组进行了过滤,使用count()方法对过滤后的数组进行了大小统计,且使parallelStream()方法为集合创建了并行流,自动采用并行运算提高速度。在更复杂的场景,还可以用forEach()、map()、limit()、sorted()、collect()等方法进行进一步的流运算。

三、典型接口详解

本节以典型场景为例,列出Stream API常用接口的用法,并附上相应代码。
需要说明的是,Stream API中存在很多方法重载,同名方法本文中可能仅列举一个,请读者注意~

3.1 Stream的生成

java8 Stream API支持串行或并行的方式,可以简单看下jdk1.8 Collection接口的源码(注释只截取部分):

    /**     * @return a sequential {@code Stream} over the elements in this collection     * @since 1.8     */    default Stream stream() {        return StreamSupport.stream(spliterator(), false);    }    /**     * @return a possibly parallel {@code Stream} over the elements in this collection     * @since 1.8     */    default Stream parallelStream() {        return StreamSupport.stream(spliterator(), true);    }

可以看出,在集合类的接口(Collection)中,分别用两种方式来生成:

1. 串行流 : stream()
2. 并行流 : parallelStream()

应该注意的是,使用parallelStream()生成并行流后,对集合元素的遍历是无序的。

3.2 forEach()方法

简单看下forEach()方法的源码(注释只截取部分):

    /**     * Performs an action for each element of this stream.     */    void forEach(Consumer action);

forEach()方法的参数为一个Consumer(消费函数,一个函数式接口)对象,forEach()方法用来迭代流中的每一个数据,例如:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);                numbers.stream().forEach(n ->  System.out.println("List element: " + n));    }

上例中,对数组的每个元素进行串行遍历,并打印每个元素的值。

ps:
集合的顶层接口Iterable中也投forEach方法,可以直接对数组元素进行遍历:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);                numbers.forEach(n ->  System.out.println("List element: " + n));    }

当然用Strem API的好处不仅仅是遍历~~~

3.3 map()方法

简单看下map()方法的源码(注释只截取部分):

    /**     * Returns a stream consisting of the results of applying the given function to the elements of this stream.     * @param  The element type of the new stream     * @param mapper a non-interfering,     *               stateless     *               function to apply to each element     * @return the new stream     */     Stream map(Function mapper);

map()方法的参数为Function(函数式接口)对象,map()方法将流中的所有元素用Function对象进行运算,生成新的流对象(流的元素类型可能改变)。举例如下:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);                numbers.stream().map( n -> Math.abs(n)).forEach(n ->  System.out.println("Element abs: " + n));    }

上例中,用map()方法计算了所有数组元素的绝对值并生成了一个新的流,然后再用forEach()遍历打印。

3.4 flatMap()方法

简单看下flatMap()方法的源码(省略注释):

  Stream flatMap(Function> mapper);

显然,跟map()方法不同的是,Function函数的返回值类型是Stream类型,而不是R类型,即Function函数返回一个Stream流,这样flatMap()能够将一个二维的集合映射成一个一维的集合,比map()方法拥有更高的映射深度(此处可能有一点绕,可结合例子理解),作个简单示例如下:

有一个字符串数组:

List list = Arrays.asList("1 2", "3 4", "5 6");

其有三个元素,每个元素有两个数组并用空格隔开,如果每个元素以空格分割成2个元素,并遍历打印这6个元素,

用flatMap()方法如下:

list.stream().flatMap(item -> Arrays.stream(item.split(" "))).forEach(System.out::println);

而用map()方法:

 list.stream().map(item -> Arrays.stream(item.split(" "))).forEach(n ->n.forEach(System.out::println));

可见,用map()方法,返回了一个"流中流",需要在每个Stream元素遍历时,再加一层forEach进行遍历。

3.5 filter()方法

简单看下filter()方法的源码(注释只截取部分):

    /**     * Returns a stream consisting of the elements of this stream that match the given predicate.     *     * 

This is an intermediate operation. * * @param predicate a non-interfering, * stateless * predicate to apply to each element to determine if it should be included * @return the new stream */ Stream filter(Predicate predicate);

filter()方法的参数为Predicate(函数式接口)对象,再lambda表达式的讲解中我们提到过这个接口,一般用它进行过滤。正如第二章中示例:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);              long count = numbers.parallelStream().filter(i -> i>0).count();                System.out.println("Positive count: " + count);    }

用filter方法很容易过滤出整数数组中的自然数。

3.6 reduce()方法

reduce操作又称为折叠操作,用于将流中的所有值合成一个。reduce()方法的源码(不提供计算初始值的reduce方法)(省略注释):

Optional reduce(BinaryOperator accumulator);

reduce()方法参数为BinaryOperator类型的累加器(它接受两个类型相同的参数,返回值类型跟参数类型相同),返回一个Optional对象。
 实际上,Stream API中的mapToInt()方法返回的IntStream接口有类似的 average()、count()、sum()等方法就是做reduce操作,类似的还有mapToLong()、mapToDouble() 方法。当然,我们也可以用reduce()方法来自定义reduce操作。例如我们用reduce()方法来进行整数数组求和操作:

    public static void main(String[] args)    {        List numbers = Arrays.asList(-1, -2, 0, -1, 4, 5, 1);                Integer total = numbers.stream().reduce((t, n) -> t + n).get();                System.out.println("Total: " + total);    }

上例中利用reduce()方法结合lambda表达式轻易的实现了数组的求和功能。

3.7 collect()方法

简单看下collect()方法的源码(注释只截取部分):

    /**     * @param  the type of the result     * @param  the intermediate accumulation type of the {@code Collector}     * @param collector the {@code Collector} describing the reduction     * @return the result of the reduction     */     R collect(Collector collector);

collect()方法的参数为一个java.util.stream.Collector类型对象,可以用java.util.stream.Collectors工具类提供的静态方法来生成,Collectors类实现很多的归约操作,如Collectors.toList()、Collectors.toSet()、Collectors.joining()(joining适用于字符串流)等。看一个简单示例:

    public static void main(String[] args)    {          List numbers = Arrays.asList(-1, -2, 0, 4, 5);                List abss = numbers.stream().map( n -> Math.abs(n)).collect(Collectors.toList());                System.out.println("Abs list: " + abss);    }

上例中,用map()方法生成新的流,再用collect()方法返回原数组的绝对值数组。

3.8 summaryStatistics()方法进行数值统计

其实summaryStatistics()方法并不是Stream接口的方法,而是Stream API采用mapToInt()、mapToLong()、mapToDouble()三个方法分别生成IntStream 、LongStream 、DoubleStream 三个接口类型的对象,这个方法的参数分别为3个函数式接口ToIntFunction、ToLongFunction、ToDoubleFunction,使用时可以用lambda表达式计算返回对应的int、long、double类型即可,简单看下这三个方法的源码(省略注释):

    IntStream mapToInt(ToIntFunction mapper);    LongStream mapToLong(ToLongFunction mapper);    DoubleStream mapToDouble(ToDoubleFunction mapper);

IntStream 、LongStream 、DoubleStream 三个接口类型都有一个summaryStatistics()方法,其中,

  1. IntStream 的方法是:

 IntSummaryStatistics summaryStatistics();
  1. LongStream 的方法是:

 LongSummaryStatistics summaryStatistics();
  1. DoubleStream 的方法是:

 DoubleSummaryStatistics summaryStatistics();

在IntSummaryStatistics、LongSummaryStatistics 、DoubleSummaryStatistics 三个接口类型(位于java.util包下)中,都有诸如统计数量、最大值、最小值、求和、平均值等方法(方法名和返回类型可能不同),利用这些方法我们可以方便的进行数值统计。以IntSummaryStatistics工具包 为例:

    public static void main(String[] args)    {        List numbers = Arrays.asList(-1, -2, 0, 4, 5);                IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();                System.out.println("Max : " + stats.getMax());        System.out.println("Min : " + stats.getMin());        System.out.println("Sum : " + stats.getSum());        System.out.println("Average : " + stats.getAverage());        System.out.println("Count : " + stats.getCount());    }

3.9 其它方法

Stream API还有一些其它的方法,比如:
    limit()    获取指定数量的流
    sorted()   对流进行排序
    distinct()  去重
    skip()    跳过指定数量的元素
    peek()   生成一个包含原Stream的所有元素的新Stream,并指定消费函数
    count()   计算元素数量
    ......

四、注意事项

Stream中的操作从概念上讲分为中间操作和终端操作:

要理解中间操作和终端操作的概念,防止埋坑~

14个常用Stream:

1. forEach 循环

@Testpublic void forEach(){    // 你不鸟我,我也不鸟你    List list = Arrays.asList("you", "don't", "bird", "me", ",",                                        "I", "don't", "bird", "you");    // 方式一:JDK1.8之前的循环方式    for (String item: list) {        System.out.println(item);    }    // 方式二:使用Stream的forEach方法    // void forEach(Consumer action)    list.stream().forEach(item -> System.out.println(item));    // 方式三:方式二的简化方式    // 由于方法引用也属于函数式接口,所以方式二Lambda表达式也可以使用方法引用来代替    // 此种方式就是方式一、方式二的简写形式    list.stream().forEach(System.out::println);}

2. filter 过滤

public class User {    private Long id;    private String phone;    private Integer age;    public User(){}    public User(Long id, String username, Integer age) {        this.id = id;        this.username = username;        this.age = age;    }    // Getter & Setter & toString}@Testpublic void filter(){    List users = Arrays.asList(            new User(1L, "mengday", 28),            new User(2L, "guoguo", 18),            new User(3L, "liangliang", 17)    );    // Stream filter(Predicate predicate);    users.stream().filter(user -> user.getAge() > 18).forEach(System.out::println);}

3. map 映射

@Testpublic void map(){    List list = Arrays.asList("how", "are", "you", "how", "old", "are", "you", "?");    //  Stream map(Function mapper);    list.stream().map(item -> item.toUpperCase()).forEach(System.out::println);}

4. flatMap

@Testpublic void flatMap(){    List a = Arrays.asList(1, 2, 3);    List b = Arrays.asList(4, 5, 6);    //  Stream flatMap(Function> mapper)    List> collect = Stream.of(a, b).collect(Collectors.toList());    // [[1, 2, 3], [4, 5, 6]]     System.out.println(collect);    // 将多个集合中的元素合并成一个集合    List mergeList = Stream.of(a, b).flatMap(list -> list.stream()).collect(Collectors.toList());    // [1, 2, 3, 4, 5, 6]    System.out.println(mergeList);    // 通过Builder模式来构建    Stream stream = Stream.builder().add("hello").add("hi").add("byebye").build();}

5. sorted 排序

@Testpublic void sort(){    List list = Arrays.asList("c", "e", "a", "d", "b");    // Stream sorted(Comparator comparator);    // int compare(T o1, T o2);    list.stream().sorted((s1, s2) -> s1.compareTo(s2)).forEach(System.out::println);}

6. distinct 去重复

@Testpublic void distinct(){    // 知之为知之,不知为不知    Stream stream = Stream.of("know", "is", "know", "noknow", "is", "noknow");    stream.distinct().forEach(System.out::println); // know is noknow}

7. count 总数量

@Testpublic void count(){    Stream stream = Stream.of("know", "is", "know", "noknow", "is", "noknow");    long count = stream.count();    System.out.println(count);}

8. min、max

@Testpublic void min(){    List list = Arrays.asList("1", "2", "3", "4", "5");    // Optional min(Comparator comparator);    Optional optional = list.stream().min((a, b) -> a.compareTo(b));    String value = optional.get();    System.out.println(value);}

9. skip、limit

@Testpublic void skip(){    List list = Arrays.asList("a", "b", "c", "d", "e");    // Stream skip(long n)    list.stream().skip(2).forEach(System.out::println);  // c、d、e}@Testpublic void limit(){    List list = Arrays.asList("a", "b", "c", "d", "e");    list.stream().skip(2).limit(2).forEach(System.out::println);    // c、d}

10. collect

@Testpublic void collect(){    List list = Arrays.asList("a", "b", "c", "d", "e");    // Stream -> Collection    List collect = list.stream().collect(Collectors.toList());    // Stream -> Object[]    Object[] objects = list.stream().toArray();}

11. concat

@Testpublic void concat(){    List list = Arrays.asList("a", "b");    List list2 = Arrays.asList("c", "d");    Stream concatStream = Stream.concat(list.stream(), list2.stream());    concatStream.forEach(System.out::println);}

12. anyMatch、allMatch

@Testpublic void match(){    // 你给我站住    List list = Arrays.asList("you", "give", "me", "stop");    // boolean anyMatch(Predicate predicate);    // parallelStream可以并行计算,速度比stream更快    boolean result = list.parallelStream().anyMatch(item -> item.equals("me"));    System.out.println(result);}/*** anyMatch伪代码 * 如果集合中有一个元素满足条件就返回true * @return */public  boolean anyMatch() {    List list = Arrays.asList("you", "give", "me", "stop");    for (String item : list) {        if (item.equals("me")) {            return true;        }    }        return false;    }

13. reduce 归纳

@Testpublic void reduce(){    Stream stream = Stream.of("you", "give", "me", "stop");    // Optional reduce(BinaryOperator accumulator);    Optional optional = stream.reduce((before, after) -> before + "," + after);    optional.ifPresent(System.out::println);    // you,give,me,stop}

BigDecimal求和

public static void main(String[] args) {    List list = Arrays.asList(            new BigDecimal("11.11"),            new BigDecimal("22.22"),            new BigDecimal("33.33")    );    // 66.66    BigDecimal sum = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);    System.out.println(sum);}

14. findFirst、findAny

@Testpublic void findFirst(){    Stream stream = Stream.of("you", "give", "me", "stop");    String value = stream.findFirst().get();    System.out.println(value);}@Testpublic void findAny(){    Stream stream = Stream.of("you", "give", "me", "stop");    String value2 = stream.findAny().get();    System.out.println(value2);}

"java8的Stream特性是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 元素 方式 接口 数组 类型 函数 对象 生成 参数 数据 注释 源码 消费 运算 三个 代码 数据源 数量 示例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技海报 互联网科技公司简介 广州大一互联网络科技有限公司 科技和互联网公司 互联网科技有限公司经营范围 互联网金融与金融科技 互联网的科技创新 广州凡科互联网科技 金融科技和互联网金融 西藏七维空间互联网科技有限公司 济南华为互联网科技产业总部基地 北京华百购互联网科技有限公司 广州市恰铎互联网科技有限公司 中国互联网公司排名锤子科技 长沙互联网科技 山东有哪些互联网科技公司 广州燕处互联网科技有限公司 云鲸互联网络科技有限公司 北京天晋互联网科技有限公司 青岛易易互联网科技 互联网科技产业 互联网科技汛 衡水科技产业互联网平台 崇明区互联网教育科技诚信经营 链环科技传统企业怎么转型互联网 科技类公司包括互联网吗 特约风豹互联网科技为什么扣费 互联网金融科技公司的优势 萌小萌互联网科技河南有限公司 重庆科技产业互联网有哪些
0