Java8 Stream详解及中间操作方法使用示例(一)

news2024/11/28 1:35:49

Java 8 引入了 Stream API,提供了一种新的处理集合和数组的方式。Stream API 可以让我们更加便捷、灵活地处理数据,尤其是大规模数据。在这里,我将详细介绍 Java 8 中的 Stream API。

什么是 Stream

        Stream 是 Java 8 中引入的一个新的概念,它代表着一种元素序列的表现形式。具体来说,它是对集合和数组等数据源的抽象,类似于 I/O 流,但它不会改变数据源本身。Stream 的出现使得我们可以更方便、更高效地对数据进行操作,它可以帮助我们轻松地实现过滤、映射、排序、统计等操作,同时还能够支持并行处理,大大提高了程序的效率。

Stream 操作类型

Stream API 的操作可以分为以下几类:

  1. 创建流的操作:创建流指的是将一个集合或其他数据源转换为 Stream 流对象的过程。通常情况下,我们可以使用 Stream 类的静态方法来创建流对象,如 Stream.of()、Collections.stream() 等。这些方法将返回一个 Stream 流对象,该对象可用于对数据进行各种操作。下面是一些常用的创建流的方法。
    of(T... values):创建一个由指定元素组成的流。
    
    empty():创建一个空的流。
    
    generate(Supplier<T> s):创建一个无限流,每次调用 get() 方法都会生成新的数据。
    
    iterate(T seed, UnaryOperator<T> f):创建一个无限流,在每次迭代时都会应用指定的函数。
    
    concat(Stream<? extends T> a, Stream<? extends T> b):创建一个包含两个流的顺序流,先是流 a,再是流 b。
    
    builder():创建一个用于构建链式操作的 Builder 对象。
    
    ofNullable(T t):创建一个包含零个或一个元素的流,元素为指定对象(可以为 null)。
    
    range(int startInclusive, int endExclusive):创建一个包含从 startInclusive 开始(含)到 endExclusive 结束(不含)的整数序列流。
    
    rangeClosed(int startInclusive, int endInclusive):创建一个包含从 startInclusive 开始(含)到 endInclusive 结束(含)的整数序列流。

  2. 中间操作(Intermediate Operations):中间操作是指转换 Stream 类型的操作,可以将一个 Stream 转换成另一个 Stream。下面是一些常用的中间操作方法。这些方法都是惰性求值的,只会创建一个新的 Stream 对象,而不是从数据源中读取数据。
    filter(Predicate<T> predicate):根据指定的条件过滤流中的元素。
    
    map(Function<T, R> mapper):将流中的元素映射为另外一种类型。
    
    flatMap(Function<T, Stream<R>> mapper):将流中的每个元素都转换成一个新的流,然后把所有的新流合并为一个大流。
    
    distinct():去除流中的重复元素。
    
    sorted():按自然顺序排序流中的元素。
    
    sorted(Comparator<T> comparator):按指定的比较器来排序流中的元素。
    
    peek(Consumer<T> action):对每个元素执行指定的操作,并且返回一个新的流。
    
    limit(long maxSize):从流中截取指定数量的元素。
    
    skip(long n):跳过前面的n个元素,返回剩余的元素。
  3. 结束操作(Terminal Operations):结束操作是指结束 Stream 该如何处理的操作,并且会触发 Stream 的执行。下面是一些常用的结束操作方法。结束操作会对数据源进行遍历,因此是及早求值的。
    forEach(Consumer<T> action):对流中的每个元素执行指定的操作。
    
    toArray():将流中的元素转换成数组。
    
    reduce(T identity, BinaryOperator<T> accumulator):使用指定的累加器对流中的元素进行聚合。
    
    collect(Collector<T,A,R> collector):将流中的元素收集到一个容器中。
    
    min(Comparator<T> comparator):返回流中的最小元素。
    
    max(Comparator<T> comparator):返回流中的最大元素。
    
    count():返回流中元素的数量。
    
    anyMatch(Predicate<T> predicate):判断流中是否有任意一个元素匹配指定的条件。
    
    allMatch(Predicate<T> predicate):判断流中是否所有元素都匹配指定的条件。
    
    noneMatch(Predicate<T> predicate):判断流中是否没有任何一个元素匹配指定的条件。
    
    findFirst():返回流中的第一个元素。
    
    findAny():返回流中的任意一个元素。
  4. 其他方法:Java 8 Stream API 还提供了一些其他的方法,可以帮助我们更好地处理流中的数据。其中,parallel() 和 sequential() 可以用来选择并行处理或者串行处理,isParallel() 可以帮助我们判断当前流是否为并行流。而 unordered() 可以告诉流不必保证元素的顺序。onClose() 方法则可以在流关闭时执行一个指定的处理程序。最后,使用 spliterator() 方法可以创建一个 Spliterator 对象,用来遍历流中的元素。

    parallel():将流转为并行流(多线程处理),可以提高处理效率。
    
    sequential():将流转为串行流(单线程处理)。
    
    unordered():告诉流不必保证元素的顺序。
    
    isParallel():判断流是否是并行流。
    
    onClose(Runnable closeHandler):在流关闭时执行指定的处理程序。
    
    spliterator():创建一个 Spliterator 来遍历流的元素。

Stream中间操作方法详细介绍

filter(Predicate<? super T> predicate)

 filter(Predicate<? super T> predicate) 方法是用来过滤流中的元素,返回一个新的流,其中仅包含满足指定条件的元素。

下面是一个使用示例:

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

public class StreamFilterExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        
        List<Integer> filteredList = list.stream()
                                         .filter(n -> n % 2 == 0)
                                         .collect(Collectors.toList());

        System.out.println(filteredList); // 输出 [2, 4]
    }
}

以上代码展示了如何使用 filter(Predicate<? super T> predicate) 方法来过滤流中的元素。首先创建了一个整型列表 list,然后通过 stream() 方法将其转换为一个流。接着,使用 filter(n -> n % 2 == 0) 方法得到一个新的流,其中仅包含偶数元素,并通过 collect(Collectors.toList()) 方法将其中的元素收集到一个列表中,得到一个只包含偶数的整型列表 filteredList,最终将其打印出来。

需要注意的是, filter(Predicate<? super T> predicate) 方法使用了一个 Predicate 接口类型的参数,即一个函数式接口,用于筛选流中符合指定条件的元素。在上述代码中,使用的是一个 lambda 表达式 n -> n % 2 == 0,表示筛选偶数元素。

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

map() 方法是 Stream 类中的一个中间操作方法,它接收一个 Function 类型的参数 mapper,用于将流中每个元素按照指定规则映射成另一个元素并生成一个新的流。具体来说,该方法会对流中的每个元素应用 mapper 函数,并将函数返回值构成新流。

例如,假设有一个由字符串构成的流,现在需要获取每个字符串的长度,并生成一个新的整数流,可以使用 map() 方法实现:

List<String> strList = Arrays.asList("Java", "Python", "C#", "JavaScript");
strList.stream()
       .map(str -> str.length())
       .forEach(System.out::println);

以上代码中,首先从字符串列表中创建一个 Stream,然后通过 map() 方法将每个字符串转换成其长度,并生成一个新的整数流。最后通过 forEach() 方法输出每个元素到控制台。

需要注意的是,由于 map() 方法是一个中间操作方法,因此对流的操作不会立即执行,而是在遇到终止操作方法时才会执行。同时,由于 map() 方法只是映射了流中的每个元素,并未改变原始流,因此不会影响流中后续元素的处理。

另外,需要注意 map() 方法的映射函数不能返回 null,否则会抛出 NullPointerException 异常。如果需要在映射过程中排除某些元素,可以使用 filter() 方法。

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

flatMap() 方法是 Stream 类中的一个中间操作方法,它将一个元素映射为一个 Stream,然后把所有 Stream 合并成一个 Stream。具体来说,flatMap() 方法接收一个函数作为参数,该函数用于将一个元素转换为另一个 StreamflatMap() 方法会遍历每个元素,并将该元素传递给该函数进行转换,最终将所有 Stream 合并成一个新的 Stream

例如,假设有一个包含多个字符串的列表,现在需要将每个字符串转换成一个字符数组,并将所有字符数组合并成一个字符串列表,可以使用 flatMap() 方法实现:

List<String> strList = Arrays.asList("hello", "world");
List<String> charList = strList.stream()
                               .flatMap(str -> Arrays.stream(str.split("")))
                               .collect(Collectors.toList());
System.out.println(charList); // 输出结果为 ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

以上代码中,首先从字符串列表中创建一个 Stream,然后对每个字符串执行 Arrays.stream(str.split("")) 方法,将字符串转换为字符数组并返回一个 Stream,最后通过 flatMap() 将所有 Stream 合并成一个新的 Stream,再通过 collect() 方法将 Stream 转换为 List

需要注意的是,如果函数返回的是一个数组或集合等对象,那么 flatMap() 方法会直接将这个对象添加到结果 Stream 中,而不是将它的元素逐个添加到结果 Stream 中。如果需要将这个对象中的元素逐个添加到结果 Stream 中,可以使用 flatMap() 方法配合 Arrays.stream()Collection.stream() 方法实现。

例如,假设有一个包含多个单词的列表,现在需要将其中长度大于 3 的单词的字符转换成小写字母,可以使用 flatMap() 方法实现:

List<String> words = Arrays.asList("Java", "Stream", "API");
List<String> letters = words.stream()
                             .filter(word -> word.length() > 3)
                             .flatMap(word -> Arrays.stream(word.toLowerCase().split("")))
                             .collect(Collectors.toList());
System.out.println(letters); // 输出结果为 ["j", "a", "v", "a", "s", "t", "r", "e", "a", "m"]

以上代码中,首先从单词列表中创建一个 Stream,然后过滤出长度大于 3 的单词并对每个单词执行 Arrays.stream(word.toLowerCase().split("")) 方法,将单词转换为小写字母字符数组并返回一个 Stream,最后通过 flatMap() 将所有 Stream 合并成一个新的 Stream,再通过 collect() 方法将 Stream 转换为 List。注意,由于 toLowerCase() 方法返回的是一个字符串对象,因此需要先调用 split() 方法将字符串拆分成字符数组。 

flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)

flatMapToDouble() 方法是 Stream 类中的一个中间操作方法,它将一个元素映射为一个 DoubleStream,并将所有 DoubleStream 合并成一个新的 DoubleStream。具体来说,flatMapToDouble() 方法接收一个函数作为参数,该函数用于将一个元素转换为另一个 DoubleStreamflatMapToDouble() 方法会遍历每个元素,并将该元素传递给该函数进行转换,最终将所有 DoubleStream 合并成一个新的 DoubleStream

例如,假设有一个包含多个字符串的列表,现在需要将每个字符串转换成一个浮点数数组,并将所有浮点数求和,可以使用 flatMapToDouble() 方法实现:

List<String> strList = Arrays.asList("1.0", "2.0", "3.0");
double sum = strList.stream()
                    .flatMapToDouble(str -> DoubleStream.of(Double.parseDouble(str)))
                    .sum();
System.out.println(sum); // 输出结果为 6.0

以上代码中,首先从字符串列表中创建一个 Stream,然后对每个字符串执行 DoubleStream.of(Double.parseDouble(str)) 方法,将字符串转换为浮点数并返回一个 DoubleStream,最后通过 flatMapToDouble() 将所有 DoubleStream 合并成一个新的 DoubleStream,并调用 sum() 方法求和。

需要注意的是,如果函数返回的是一个数组或集合等对象,那么 flatMapToDouble() 方法会直接将这个对象添加到结果 DoubleStream 中,而不是将它的元素逐个添加到结果 DoubleStream 中。如果需要将这个对象中的元素逐个添加到结果 DoubleStream 中,可以使用 flatMapToDouble() 方法配合 Arrays.stream()Collection.stream() 方法实现。

例如,假设有一个包含多个单词的列表,现在需要将其中长度大于 3 的单词的字符转换成小写字母的 ASCII 码,并将所有 ASCII 码求平均值,可以使用 flatMapToDouble() 方法实现:

List<String> words = Arrays.asList("Java", "Stream", "API");
double avg = words.stream()
                  .filter(word -> word.length() > 3)
                  .flatMapToDouble(word -> word.toLowerCase().chars().asDoubleStream())
                  .average()
                  .orElse(0.0);
System.out.println(avg); // 输出结果为 99.54545454545455

 以上代码中,首先从单词列表中创建一个 Stream,然后过滤出长度大于 3 的单词并对每个单词执行 word.toLowerCase().chars().asDoubleStream() 方法,将单词转换为小写字母字符数组并返回一个 DoubleStream,最后通过 flatMapToDouble() 将所有 DoubleStream 合并成一个新的 DoubleStream,并调用 average() 方法求平均值。注意,由于 chars() 方法返回的是一个 IntStream,因此需要调用 asDoubleStream() 方法将其转换为 DoubleStream。如果列表为空,可以通过调用 orElse() 方法设置一个默认值。

flatMapToInt(Function<? super T,? extends IntStream> mapper)

flatMapToInt() 方法是 Stream 类中的一个中间操作方法,它将一个元素映射为一个 IntStream,并将所有 IntStream 合并成一个新的 IntStream。具体来说,flatMapToInt() 方法接收一个函数作为参数,该函数用于将一个元素转换为另一个 IntStreamflatMapToInt() 方法会遍历每个元素,并将该元素传递给该函数进行转换,最终将所有 IntStream 合并成一个新的 IntStream

例如,假设有一个包含多个字符串的列表,现在需要将每个字符串转换成一个整数数组,并将所有整数求和,可以使用 flatMapToInt() 方法实现:

List<String> strList = Arrays.asList("1", "2", "3");
int sum = strList.stream()
                 .flatMapToInt(str -> IntStream.of(Integer.parseInt(str)))
                 .sum();
System.out.println(sum); // 输出结果为 6

以上代码中,首先从字符串列表中创建一个 Stream,然后对每个字符串执行 IntStream.of(Integer.parseInt(str)) 方法,将字符串转换为整数并返回一个 IntStream,最后通过 flatMapToInt() 将所有 IntStream 合并成一个新的 IntStream,并调用 sum() 方法求和。

需要注意的是,如果函数返回的是一个数组或集合等对象,那么 flatMapToInt() 方法会直接将这个对象添加到结果 IntStream 中,而不是将它的元素逐个添加到结果 IntStream 中。如果需要将这个对象中的元素逐个添加到结果 IntStream 中,可以使用 flatMapToInt() 方法配合 Arrays.stream()Collection.stream() 方法实现。

例如,假设有一个包含多个单词的列表,现在需要将其中长度大于 3 的单词的字符转换成小写字母的 ASCII 码,并将所有 ASCII 码求平均值,可以使用 flatMapToInt() 方法实现:

List<String> words = Arrays.asList("Java", "Stream", "API");
double avg = words.stream()
                  .filter(word -> word.length() > 3)
                  .flatMapToInt(word -> word.toLowerCase().chars())
                  .average()
                  .orElse(0.0);
System.out.println(avg); // 输出结果为 99.54545454545455

 以上代码中,首先从单词列表中创建一个 Stream,然后过滤出长度大于 3 的单词并对每个单词执行 word.toLowerCase().chars() 方法,将单词转换为小写字母字符数组并返回一个 IntStream,最后通过 flatMapToInt() 将所有 IntStream 合并成一个新的 IntStream,并调用 average() 方法求平均值。注意,由于 chars() 方法返回的是一个 IntStream,因此不需要调用其他方法进行转换。如果列表为空,可以通过调用 orElse() 方法设置一个默认值。

flatMapToLong(Function<? super T,? extends LongStream> mapper)

flatMapToLong() 方法是 Stream 类中的一个中间操作方法,它将一个元素映射为一个 LongStream,并将所有 LongStream 合并成一个新的 LongStream。具体来说,flatMapToLong() 方法接收一个函数作为参数,该函数用于将一个元素转换为另一个 LongStreamflatMapToLong() 方法会遍历每个元素,并将该元素传递给该函数进行转换,最终将所有 LongStream 合并成一个新的 LongStream

例如,假设有一个包含多个字符串的列表,现在需要将每个字符串转换成一个长整数数组,并将所有长整数求和,可以使用 flatMapToLong() 方法实现:

List<String> strList = Arrays.asList("1", "2", "3");
long sum = strList.stream()
                  .flatMapToLong(str -> LongStream.of(Long.parseLong(str)))
                  .sum();
System.out.println(sum); // 输出结果为 6

以上代码中,首先从字符串列表中创建一个 Stream,然后对每个字符串执行 LongStream.of(Long.parseLong(str)) 方法,将字符串转换为长整数并返回一个 LongStream,最后通过 flatMapToLong() 将所有 LongStream 合并成一个新的 LongStream,并调用 sum() 方法求和。

需要注意的是,如果函数返回的是一个数组或集合等对象,那么 flatMapToLong() 方法会直接将这个对象添加到结果 LongStream 中,而不是将它的元素逐个添加到结果 LongStream 中。如果需要将这个对象中的元素逐个添加到结果 LongStream 中,可以使用 flatMapToLong() 方法配合 Arrays.stream()Collection.stream() 方法实现。

例如,假设有一个包含多个单词的列表,现在需要将其中长度大于 3 的单词的字符转换成小写字母的 ASCII 码,并将所有 ASCII 码求平均值,可以使用 flatMapToLong() 方法实现:

List<String> words = Arrays.asList("Java", "Stream", "API");
double avg = words.stream()
                  .filter(word -> word.length() > 3)
                  .flatMapToLong(word -> word.toLowerCase().chars().asLongStream())
                  .average()
                  .orElse(0.0);
System.out.println(avg); // 输出结果为 99.54545454545455

以上代码中,首先从单词列表中创建一个 Stream,然后过滤出长度大于 3 的单词并对每个单词执行 word.toLowerCase().chars().asLongStream() 方法,将单词转换为小写字母字符数组并返回一个 LongStream,最后通过 flatMapToLong() 将所有 LongStream 合并成一个新的 LongStream,并调用 average() 方法求平均值。注意,由于 chars() 方法返回的是一个 IntStream,因此需要调用 asLongStream() 方法将其转换为 LongStream。如果列表为空,可以通过调用 orElse() 方法设置一个默认值。 

 distinct()

distinct() 用于去除流中重复的元素,返回由不同元素组成的新流。

下面是一个使用示例:

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

public class DistinctExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 3, 2, 4, 2, 1, 5, 6, 4, 3);
        
        List<Integer> distinctList = list.stream()
                                         .distinct()
                                         .collect(Collectors.toList());

        System.out.println(distinctList); // 输出 [1, 3, 2, 4, 5, 6]
    }
}

以上代码展示了如何使用 distinct() 方法去除流中重复的元素。首先创建了一个整型列表 list,然后通过 stream() 方法将其转换为一个流。接着,使用 distinct() 方法得到一个由不同元素组成的新流,并通过 collect(Collectors.toList()) 方法将其中的元素收集到一个列表中,得到一个没有重复元素的整型列表 distinctList,最终将其打印出来。

需要注意的是,distinct() 方法使用了对象的 hashCode()equals() 方法来判断元素是否重复。因此,要确保列表中的元素已正确地实现了这两个方法。

sorted()

sorted()方法是一个中间操作,用于对Stream对象的元素进行排序并返回一个新的Stream对象。该方法会使用元素所属类的compareTo()方法进行默认排序,也可以接收一个Comparator函数来自定义排序规则。

具体用法如下:

  1. 创建一个包含多个元素的Stream对象。
  2. 调用sorted()方法,并可选地传入一个Comparator函数。
  3. 该方法将对Stream对象中的元素进行排序,并返回一个新的Stream对象。

例如,以下代码演示了如何使用sorted()方法对整数流进行排序:

List<Integer> list = Arrays.asList(5, 3, 8, 1, 4);
Stream<Integer> sortedStream = list.stream().sorted();
sortedStream.forEach(System.out::println); // 输出 1 3 4 5 8

上述代码创建一个Integer类型的列表,并将其转换成Stream对象。接下来调用sorted()方法,该方法使用默认排序规则对Stream对象中的元素进行排序,将返回一个新的Stream对象。最后使用forEach()方法遍历新的Stream对象,并将其输出到控制台上。

需要注意的是,Stream对象是惰性求值的,因此在调用sorted()方法时并不会立即执行排序操作,而是在遍历Stream对象时才进行排序。如果在排序时使用了Comparator函数,则需要确保元素类型实现了Comparable接口。

sorted(Comparator<? super T> comparator)

sorted(Comparator<? super T> comparator)方法是一个中间操作,用于对Stream对象的元素进行排序并返回一个新的Stream对象。该方法使用传入的Comparator函数来自定义排序规则。

具体用法如下:

  1. 创建一个包含多个元素的Stream对象。
  2. 调用sorted(Comparator<? super T> comparator)方法,并传入一个Comparator函数。
  3. 该方法将使用传入的Comparator函数对Stream对象中的元素进行排序,并返回一个新的Stream对象。

例如,以下代码演示了如何使用sorted()方法和Comparator函数对字符串流进行排序:

List<String> list = Arrays.asList("java", "python", "ruby", "c++");
Stream<String> sortedStream = list.stream().sorted((s1, s2) -> s1.length() - s2.length());
sortedStream.forEach(System.out::println); // 输出 c++ java ruby python

上述代码创建一个String类型的列表,并将其转换成Stream对象。接下来调用sorted()方法,并传入一个Comparator函数,该函数按照字符串长度进行排序。该方法会返回一个新的Stream对象,其中的元素已按照指定规则排序。最后使用forEach()方法遍历新的Stream对象,并将其输出到控制台上。

需要注意的是,传入的Comparator函数可以根据任意规则进行排序,不一定要依赖元素所属类的compareTo()方法。由于Stream对象是惰性求值的,因此在调用sorted()方法时并不会立即执行排序操作,而是在遍历Stream对象时才进行排序。

 peek(Consumer<? super T> action)

peek(Consumer<? super T> action)方法是一个中间操作,用于在Stream的元素流中插入一些操作,这些操作可以查看、调试或记录Stream中的元素。该方法不会改变原始Stream中的元素。

具体用法如下:

  1. 创建一个包含多个元素的Stream对象。
  2. 调用peek(Consumer<? super T> action)方法,并传入一个Consumer对象,用于接收流中的每个元素。
  3. 该方法将在整个流上执行指定的操作,并返回新的Stream对象。

例如,以下代码演示了如何使用peek()方法输出列表中每个元素的值:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.stream().peek(x -> System.out.println("Processing element: " + x))
            .forEach(System.out::println);

输出结果为:

Processing element: 1
1
Processing element: 2
2
Processing element: 3
3
Processing element: 4
4
Processing element: 5
5

以上代码创建一个Integer类型的列表,并将其转换成Stream对象。接下来调用peek()方法,对每个元素执行操作并打印处理信息,最后再调用forEach()方法打印每个元素的值。由于peek()方法不会改变原始Stream中的元素,因此最终输出的结果与转换前的列表完全相同。

 limit(long maxSize)

limit() 方法是 Stream 类中的一个中间操作方法,它接收一个 long 型参数 maxSize,用于将原始流截取为最多包含指定数量元素的新流。如果原始流包含的元素数量小于等于 maxSize,则新流与原始流相同;如果原始流包含的元素数量大于 maxSize,则新流只包含前 maxSize 个元素。

例如,假设有一个由数字构成的流,现在需要获取其中的前五个元素,可以使用 limit() 方法实现:

List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
numList.stream()
       .limit(5)
       .forEach(System.out::println);

以上代码中,首先从数字列表中创建一个 Stream,然后通过 limit() 方法将流截取为最多包含 5 个元素的新流,最后通过 forEach() 方法输出每个元素到控制台。由于调用了 limit() 方法,因此输出结果只包含前五个元素。

需要注意的是,由于 limit() 方法是一个中间操作方法,因此对流的操作不会立即执行,而是在遇到终止操作方法时才会执行。同时,由于 limit() 方法只截取了流的一部分元素,因此不会影响流中后续元素的处理。

另外,如果提供的参数值小于等于0,则新流中不包含任何元素。如果提供的参数值大于原始流的元素数量,则新流与原始流相同。

skip(long n)

skip(long n)方法是一个中间操作,用于跳过前n个元素并返回一个新的Stream对象。如果n大于流中的元素数量,则将返回一个空的Stream对象。

具体用法如下:

  1. 创建一个包含多个元素的Stream对象。
  2. 调用skip(long n)方法,并传入要跳过的元素数目n。
  3. 该方法会返回一个新的Stream对象,其中包含原始流中剩余的元素。

例如,以下代码演示了如何使用skip()方法,在字符串流中跳过前两个元素:

List<String> list = Arrays.asList("apple", "banana", "orange", "pear");
Stream<String> stream = list.stream().skip(2);
stream.forEach(System.out::println); // 输出 orange pear

上述代码创建一个String类型的列表,并将其转换成Stream对象。接下来调用skip()方法,指定要跳过前两个元素。该方法返回一个新的Stream对象,其中包含原始流中剩余的元素。最后使用forEach()方法遍历新的Stream对象,并将其输出到控制台上。

需要注意的是,Stream对象是惰性求值的,因此在调用skip()方法时并不会立即执行跳过操作,而是在遍历Stream对象时才进行跳过。跳过的元素也不会被保留在内存中,因此可以在处理大型数据集时减少内存消耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/620617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vs2022配置pcl1.13.1

下载 下载PCL预编译安装程序PCL-1.13.1-AllInOne-msvc2022-win64.exe 和要安装的PCL组件&#xff08;例如pcl-1.13.1-pdb-msvc2022-win64.zip&#xff09; 安装 双击 PCL-1.13.1-AllInOne-msvc2022-win64.exe进行安装。到图1的步骤时&#xff0c;选择第二项。 图1 下一步&am…

串口助手(布局,图标,串口号,隐藏界面,显示实时时间)

文章目录 前言一、串口助手布局二、设置软件的标题&#xff0c;图标三、显示可用串口号四、隐藏&#xff0c;显示面板五、显示实时时间总结 前言 从这篇文章开始 教大家自己制作一个串口助手软件&#xff0c;并实现基本的功能。学做一个 串口助手可以一边回顾复习 QT 的相关知…

《面试1v1》G1垃圾回收器

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 《面试1v1》 连载中… 面试官&#xff1a; G1垃圾收集器?听说很牛逼的样子! 候选人&#xff1a; 是的,G1是JDK9默认的垃圾收集器,代替了CMS收集器。它的目标是达到…

4.运算符|Java学习笔记

文章目录 运算符介绍算术运算符关系运算符&#xff08;比较运算符&#xff09;逻辑运算符赋值运算符三元运算符位运算符 运算符优先级Java命名规范关键字保留字 进制十进制转&#xff08;二/八/十六进制&#xff09;原码、反码、补码 运算符介绍 运算符是一种特殊的符号&#…

【Linux】认识Linux下的编译器gcc/g++ | 认识动静态库

本文思维导图&#xff1a; 文章目录 前言tips: 关于前两篇文章所提到的sudo指令 一、gcc/g编译器的认识和使用tips 1.预处理2. 编译3.汇编4.链接关于预编译&#xff0c;编译&#xff0c;汇编阶段的指令记忆方法 二、gcc/g指令汇总三、认识动静态库1.库的认知库的命名规则静态库…

C++ ---- 继承

目录 继承概念及定义 继承概念 继承定义 语法 继承关系和访问限定符 继承基类成员访问方式的变化 规律总结 以公有继承为例测试 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 构造函数 析构函数 拷贝构造 赋值重载 继承与友元 继承与静态成员…

ESP8266调用NTP服务器进行时间校准

一、背景知识 【1】什么是NTP服务器&#xff1f; NTP是网络时间协议&#xff08;Network Time Protocol&#xff0c;简称NTP&#xff09;&#xff0c;是一种用于同步计算机时间的协议。NTP服务器指的是提供NTP服务的计算机或设备。NTP服务器的主要功能是保证网络上的所有设备…

Linux下信号量使用总结

目录 1.Linux下信号量简介 2.POSIX信号量 2.1 无名信号量 2.2 有名信号量 3.System V信号量 1.Linux下信号量简介 信号量是解决进程之间的同步与互斥的IPC机制&#xff0c;互斥与同步关系存在的症结在于临界资源。 临界资源是在同一个时刻只容许有限个&#xff08;一般只有…

ble系统知识介绍(较为完整,持续更新中)

BLE学习 现在网上关于BLE系统的学习资料实在是太少了&#xff0c;因此本文希望能够聚集一些资料能够系统的入门BLE,本文翻译自Bluetooth_LE_Primer_Paper,还有一些网上的一些资料,如果侵害到了某些作者的权益请及时联系我 参考资料和链接 Bluetooth_LE_Primer_Paper_3MtXws-zP…

GitOps 实践之渐进式发布

本文作者&#xff1a;陈钧桐 腾讯云 CODING DevOps 高级解决方案架构师&#xff0c;从事多年技术布道工作&#xff0c;对于云原生时代下企业数字化转型、IT 与 DevOps 建设、价值流体系搭建等有丰富的经验&#xff0c;曾为多家大型企业提供咨询、解决方案以及内训服务。既关注工…

【Python小技巧】加密又提速,把.py文件编译为.pyd文件(类似dll函数库),你值得拥有!

文章目录 前言一、常见的Python文件格式有哪些&#xff1f;二、准备编译环境1. 安装cython2. 安装Microsoft C 生成工具 三、编译.py文件为.pyd文件1. 编辑原始.py文件2. 准备setup.py文件3. 进行编译 四、测试总结 前言 Python的脚本文件是开源的&#xff0c;若直接发布&#…

i.MX RT1010跨界MCU上手体验(上)

由于项目需要性价比高一些的高性能MCU&#xff0c;了解到NXP的RT1010主频高达500MHZ的MCU&#xff0c;半个月以前已经拿到官方Demo板了&#xff0c;今天抽空上电体验下&#xff0c;在此记录。这颗芯片的优势是主频高&#xff0c;功能全&#xff0c;价格合理&#xff0c;但是需要…

第六章 方法区

文章目录 前言一、&#x1f6fa; 栈、堆、方法区的交互关系二、&#x1f68e; 方法区的理解1、方法区在哪里2、方法区的演变过程 三、&#x1f697; 设置方法区的大小与 OOM1、设置方法区内存的大小2、使用CGLib 让方法区OOM3、如何解决 OOM4、方法区的内部结构5、non-final 的…

利用提示工程优化软件架构:ChatGPT的应用

ChatGPT时代的软件架构全生命周期 简介 在如今日新月异的技术环境中&#xff0c;软件架构师必须不断地寻找和采纳新的工具和方法&#xff0c;以优化开发过程&#xff0c;提高效率&#xff0c;并保证最终产出的质量。其中&#xff0c;人工智能&#xff08;AI&#xff09;已经成…

《淘宝技术这十年》读书笔记

一. 分布式时代 在系统发展的过程中&#xff0c;架构师的眼光至关重要&#xff0c;作为程序员&#xff0c;只要把功能实现即可&#xff0c;但作为架构师&#xff0c;要考虑系统的扩展性、重用性&#xff0c;对于这种敏锐的感觉&#xff0c;有人说是一种“代码洁癖”。淘宝早期…

使用双屏时两个屏幕的色调、亮度不一样如何设置?

当使用双屏时&#xff0c;即使两个屏幕的型号一致也可能存在色差的问题&#xff08;色调不一致&#xff0c;亮度不一致&#xff09;&#xff0c;以下是解决此问题的方法。 Step1.同时按下两个屏幕下方的ok按钮 Step2.此时会进入显示器的OSD界面 Step3.通过按键切换菜单 Step4.…

节省35% MCU开发成本的红外智能洗手器运用方案,N9300-S16音乐芯片

随着全国人民生活水平的逐步提升以及近期疫情影响&#xff0c;公民的健康保护意识也越来越强&#xff0c;洗手液越来越被人们重视以及提倡&#xff0c;即时在受疫情影响是2022年洗手液市场规模也是上升至恐怖34亿元产值&#xff1b;而近年来自动感应洗手液器凭借实用性、便携性…

APP测试面试题快问快答(三)

11. App安装测试的主要内容有哪些&#xff1f; App是客户端程序&#xff0c;客户端程序就需要进行安装才能使用&#xff0c;因此需要测试安装、卸载、升级测试 关注点&#xff1a;正常场景、异常场景。 正常场景&#xff1a; 1. 在不同的操作系统上安装 2. 从不同的安装渠…

windows10安装ElasticSearch

一 安装 Java环境 ElasticSearch使用Java开发的&#xff0c;依赖Java环境&#xff0c;安装 ElasticSearch 之前&#xff0c;需要先安装一个较新版本的 Java&#xff0c;jdk 1.8版本太低了&#xff0c;需要安装jdk 11或更高版本。 Java安装方法请参考 Java 15环境安装 。 二 …

详解字典树原理,代码分析leetcode208. 实现 Trie (前缀树)

0、引言 本文介绍一种能够偶快速查找字符串的树形数据结构-----字典树。介绍其原理&#xff0c;以及通过leetcode208题目这个实例&#xff0c;用数组动手实现一棵字典树&#xff0c;并完成其增、查字符串、查字符串前缀的功能。 1、字典树的应用场景 询问一个单词b&#xff0c…