Java8 教程

Java8 提取子流和组合流

在 Java8 中,limit 和 concat 是 Stream API 中两个非常有用的方法,它们分别用于限制流中元素的数量和合并两个流。

提取子流

提取子流即从一个流中截取返回流中的部分元素。如果要实现提取流前 n 个元素,需要使用 limit 方法;如果要实现分页功能,则需要使用 limit 和 skip 方法。

limit 方法

Stream.limit(n) 方法用于限制流中元素的数量,即只取前 n 个元素,并返回一个新的流。这个方法特别适用于裁剪指定长度的流。

注意:

  • 当 n<0 时,抛IllegalArgumentException异常。

  • 当 n=0 时,不取元素,返回空流。

  • 当 0<n<length 时,取前n个元素,返回新的流。

  • 当 n>=length 时,取所有元素,相当于原封不动地返回原流。

方法定义:

Stream<T> limit(long maxSize)

例如:

package com.hxstrive.jdk8.stream_api;

import java.util.ArrayList;
import java.util.List;

/**
 * limit 方法
 * @author hxstrive.com
 */
public class StreamLimitDemo {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");

        // 返回流前 2 个元素,并输出这些元素
        list.stream().limit(2).forEach(System.out::println);
        //输出:
        //one
        //two
    }

}

skip 方法

在 Java8 的 Stream API 中,而 Sream.skip(n) 与 Stream.limit(n) 正好相反。skip 方法是一个中间操作,用于跳过流中的前 N 个元素,并返回一个新的流,其中不包含这些被跳过的元素。

方法定义:

Stream<T> skip(long n)

示例:

package com.hxstrive.jdk8.stream_api;

import java.util.ArrayList;
import java.util.List;

/**
 * skip 方法
 * @author hxstrive.com
 */
public class StreamSkipDemo {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");

        // 跳过流前 2 个元素,并输出这些元素
        list.stream().skip(2).forEach(System.out::println);
        //输出:
        //three
    }

}

注意:

  • 如果 n 是一个负数,则 skip 方法会抛出 IllegalArgumentException。

  • 如果原始流的长度小于 n,则 skip 方法将返回一个空的流(不包含任何元素)。

  • skip 方法返回的流与原始流具有相同的元素类型。

  • skip 是一个中间操作,它不会立即执行任何计算。要触发流的执行,你需要调用一个终端操作,如 collect、forEach、count 等。

  • 与 Stream API 的其他方法一样,skip 方法本身不是线程安全的。如果你在多线程环境中共享 Stream,并尝试对其进行 skip 操作,可能会遇到并发问题。

组合流

组合流是将多个流连接到一起,组合成一个流。

concat 方法

在 Java8 的 Stream API 中,可以通过 Stream 的静态方法 concat 实现将两个流连接在一起。concat 方法用于将两个流合并成一个流。合并后的流包含原始流中所有元素,且保持原始流的顺序。

方法定义:

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)

注意:在重复连接构建流时要小心,访问深度级联的流的元素可能导致 StackOverflowException 。 

例如:

package com.hxstrive.jdk8.stream_api;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * concat 方法
 * @author hxstrive.com
 */
public class StreamConcatDemo {

    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("a", "b", "c");
        List<String> list2 = Arrays.asList("e", "f", "g");

        Stream<String> stream = Stream.concat(list1.stream(), list2.stream());
        System.out.println(stream.collect(Collectors.toList()));
        //输出:
        //[a, b, c, e, f, g]
    }

}

注意:

  • concat 方法只能用于两个流的合并,不能用于多个流的合并。如果需要合并多个流,请使用 flatMap 方法。

  • 合并后的流的元素顺序和原始流的元素顺序相同。

  • 如果原始流是无限流,合并后的流也将是无限流。

flatMap 方法

如果你有一个流的流(即 Stream<Stream<T>>),你可以使用 flatMap 来将它们合并成一个流。flatMap 接受一个 Function 函数式接口作为参数,该函数将每个元素映射为一个流,然后将这些流中的所有元素合并成一个流。

方法定义:

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

例如:

下面示例将 List<List<String>> 转换成一个字符串流,如下:

package com.hxstrive.jdk8.stream_api;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * flatMap 方法
 * @author hxstrive.com
 */
public class StreamFlatMapDemo2 {

    public static void main(String[] args) {
        List<List<String>> list = Arrays.asList(
                Arrays.asList("apple", "banana", "cherry"),
                Arrays.asList("dog", "elephant", "fox"));

        Stream<List<String>> stream = list.stream();

        // 传统匿名函数方式
        Stream<String> newStream = stream.flatMap(new Function<List<String>, Stream<String>>() {
            @Override
            public Stream<String> apply(List<String> strings) {
                return strings.stream();
            }
        });
        System.out.println(newStream.collect(Collectors.toList()));

        // lambda 表达式方式
        newStream = list.stream().flatMap(e -> {
            return e.stream();
        });
        System.out.println(newStream.collect(Collectors.toList()));
        //输出:
        //[apple, banana, cherry, dog, elephant, fox]
        //[apple, banana, cherry, dog, elephant, fox]
    }

}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号