Java 8新特性Stream()流

简介

Java 8 引入的 Stream API 是 Java 平台的一个重大改进,它提供了一种高效且表达力强的方式来处理数据集合(如 List、Set)。Stream API 可以让你以声明方式处理数据集合(专注于你要做什么,而不是怎么做),并且可以利用多核处理器的优势进行并行计算。Stream API 是 Java 8 引入的一个功能强大的工具,它提供了一种简洁而高效的方式来处理集合数据。通过使用 Stream,我们可以对集合进行过滤、映射、排序、聚合等操作,而无需编写繁琐的循环和条件语句。Stream 的操作可以串行执行,也可以并行执行,从而提高处理大量数据的效率。

主要特性和优点

  1. 函数式编程支持:Stream API 充分利用了 Java 8 的 Lambda 表达式和函数式编程概念。
  2. 声明式数据处理:通过 Stream API,你可以以接近自然语言的方式表达数据处理逻辑,代码更加清晰、简洁。
  3. 并行处理能力:Stream API 提供了自动的并行处理能力,可以简化并行编程的复杂性,可以自动利用多核处理器,提高处理大量数据的效率。
  4. 延迟执行:Stream API 的操作是延迟执行的,这意味着它们不会立即执行,而是等到需要结果时才执行。
  5. 无副作用:Stream API 的操作应该是无副作用的,即它们不会修改数据源。
  6. 易于集成和扩展:Stream API 可以与 Java 集合框架无缝集成,并且可以很容易地通过自定义的 Spliterator 进行扩展。

基本操作

Stream API 中的操作分为两类:中间操作(Intermediate Operations)和终端操作(Terminal Operations)。

1、中间操作:返回 Stream 本身,因此可以链式调用。中间操作是“惰性”的,即在调用终端操作之前,它们不会执行任何处理。常见的中间操作包括 filter(), map(), sorted(), limit(), skip() 等。

中间操作包括有状态和无状态操作两种:

  • 有状态操作:操作需要维护状态来正确执行,每个元素的处理可能依赖于其他元素的状态或上下文。
    例如,sorted和distinct操作,是需要维护一个状态,一个是记录位置,一个是记录是否出现过。

  • 无状态操作:每个元素的处理都是独立的,不依赖于其他元素的状态。
    例如,filter、map和flatMap,只是根据输入元素生成输出元素,而不会受到其他元素的影响。

操作类型操作方法描述
中间操作filter(Predicate<? super T> predicate)过滤流中的元素,只保留满足谓词条件的元素
map(Function<? super T, ? extends R> mapper)将流中的每个元素映射成另一种形式
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)将流中的每个元素都转换成另一个流,然后将所有流连接成一个流
distinct()去除流中的重复元素(基于元素的 equals()hashCode() 方法)
sorted()对流中的元素进行自然排序(需要元素实现了 Comparable 接口)
sorted(Comparator<? super T> comparator)使用自定义的比较器对流中的元素进行排序
peek(Consumer<? super T> action)对流中的每个元素执行操作,但不影响流本身,主要用于调试
limit(long maxSize)限制流的元素个数
skip(long n)跳过流的前n个元素

2、终端操作:返回一个结果或副作用,例如执行一个操作或返回一个非 Stream 的值。终端操作会触发 Stream 管道中所有中间操作的执行。常见的终端操作包括 forEach(), collect(), reduce(), findFirst(), min(), max() 等。

终止操作包括短路操作和非短路操作两种:

  • 短路操作:处理元素时,满足某个条件就立即返回结果,无需处理所有元素。
    例如,findFirst、findAny、anyMatch和allMatch
  • 非短路操作:指必须处理所有元素才能得到最终结果;
    例如,forEach、reduce和collect
操作类型操作方法描述
终止操作forEach(Consumer<? super T> action)遍历流中的每个元素并执行操作
toArray()将流中的元素收集到一个数组中(注意:这通常需要一个显式的类型参数,如 toArray(String[]::new)
reduce(BinaryOperator<T> accumulator)归约操作,将流中的元素组合起来,得到一个值(需要元素之间有明确的组合方式)
reduce(T identity, BinaryOperator<T> accumulator)带初始值的归约操作
collect(Collector<? super T, A, R> collector)收集操作,将流中的元素收集到一个集合中,通常与 Collectors 类一起使用
min(Comparator<? super T> comparator)找出流中的最小元素(根据提供的比较器)
max(Comparator<? super T> comparator)找出流中的最大元素(根据提供的比较器)
count()计算流中元素的个数
anyMatch(Predicate<? super T> predicate)检查流中是否存在至少一个元素满足条件
allMatch(Predicate<? super T> predicate)检查流中的所有元素是否都满足条件
noneMatch(Predicate<? super T> predicate)检查流中是否不存在任何元素满足条件
findFirst()查找流中的第一个元素(返回一个包含单个元素的 Optional
findAny()查找流中的任意一个元素(在并行流中可能不返回第一个元素)

官网: Stream()官网

一、操作

1、获取流
1.1 从集合(Collection)中获取
	@Test
    void list() {
        // 创建一个List集合
        List<String> names = Arrays.asList("John", "Alice", "Bob", "David");

        // 获取顺序流
        Stream<String> stream = names.stream();

        // 使用流进行操作(这里只是示例,没有实际的操作)
         stream.forEach(System.out::println);

        // 获取并行流
        Stream<String> parallelStream = names.parallelStream();

        // 使用并行流进行操作(这里只是示例,没有实际的操作)
        parallelStream.forEach(System.out::println);

        Set<Integer> set = new HashSet<Integer>() {{
            add(1);
            add(2);
            add(3);
        }};
        // 通过Set获取
        Stream<Integer> stream2 = set.stream();
        stream2.forEach(System.out::println);
        Map<String, String> map = new HashMap<>();
        map.put("map1","test1");
        map.put("map2","test2");
        // 通过Map.entrySet获取
        Stream<Map.Entry<String, String>> stream3 = map.entrySet().stream();
        stream3.forEach(System.out::println);
        // 通过Map.keySet获取
        Stream<String> stream4 = map.keySet().stream();
        stream4.forEach(System.out::println);
        // 通过Map.values获取
        Stream<String> stream5 = map.values().stream();
        stream5.forEach(System.out::println);
    }
1.2 从数组中获取
	@Test
    void array(){
        // 对象数组
        String[] strings = {"Hello", "World", "Java", "Stream"};
        Stream<String> stringStream = Arrays.stream(strings);

        // 基本类型数组(以int为例)
        int[] numbers = {1, 2, 3, 4, 5};
        Stream<Integer> intStream = Arrays.stream(numbers).boxed(); // 基本类型流需要装箱

        // 使用流进行操作(这里只是示例,没有实际的操作)
         stringStream.forEach(System.out::println);
         intStream.forEach(System.out::println);
    }
1.3 从其他数据源获取流
    @Test
    void stream(){
        // 使用Stream.of()从多个元素中创建流
        Stream<String> stringStream = Stream.of("Apple", "Banana", "Cherry");

        // 使用Stream.iterate()创建无限流(这里需要提供一个终止条件来限制流的大小)
        Stream<Integer> infiniteIntStream = Stream.iterate(1, n -> n + 1).limit(5); // 生成1到5的流

        // 使用Stream.generate()创建无限流(基于提供的Supplier)
        Stream<Double> randomStream = Stream.generate(Math::random).limit(10); // 生成10个随机数
        
         stringStream.forEach(System.out::println);
         infiniteIntStream.forEach(System.out::println);
         randomStream.forEach(System.out::println);
    }
1.4 从文件中创建流
    @Test
    void file(){
        // Paths.get("example.txt") 为当前工作目录下名为 example.txt 的文件,没有创建会报错,也可以写绝对路径
        try (Stream<String> stream = Files.lines(Paths.get("src/test/java/com/example/demo/example.txt"))) {
            // 读取文件每一行并打印
            stream.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
2、中间操作
2.1 map():
  • 将流中的每个元素映射到另一个元素。例如,将字符串转换为大写:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    List<String> upperCaseNames = names.stream()
    	.map(String::toUpperCase)
    	.collect(Collectors.toList());
    upperCaseNames.forEach(System.out::println);
    
2.2 filter():
  • 过滤流中的元素,只保留满足特定条件的元素。例如,过滤出长度大于3的字符串:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    List<String> longNames = names.stream()
    	.filter(name -> name.length() > 3)
    	.collect(Collectors.toList());
    longNames.forEach(System.out::println);
    
2.3 flatMap():
  • 将流中的每个元素转换为一个流,并将所有流合并成一个流。例如,将每个字符串拆分为字符并将字符流合并:

    List<String> words = Arrays.asList("hello", "world");
    List<Character> characters = words.stream()
    	.flatMap(word -> word.chars().mapToObj(c -> (char) c))
    	.collect(Collectors.toList());
    characters.forEach(System.out::println);
    
2.4 distinct():
  • 去除流中的重复元素:

    List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);
    List<Integer> distinctNumbers = numbers.stream()
    	.distinct()
    	.collect(Collectors.toList());
    distinctNumbers.forEach(System.out::println);
    
2.5 sorted():

.sorted(Comparator.reverseOrder()) 倒叙排序

Comparator.comparing(Item::getName).reversed()根据字段名倒叙排序

  • 对流中的元素进行排序。例如,按自然顺序排序:

    List<Integer> numbers = Arrays.asList(1, 2, 6, 3, 5, 4);
    List<Integer> sortedNames = numbers.stream()
    	.sorted() // 正序排序
    	.collect(Collectors.toList());
    sortedNames.forEach(System.out::println);
    
2.6 limit():
  • 限制流中元素的数量。例如,取前3个元素:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    List<String> firstThreeNames = names.stream()
    	.limit(3)
    	.collect(Collectors.toList());
    firstThreeNames.forEach(System.out::println);
    
2.7 skip():
  • 跳过流中的前N个元素。例如,跳过前2个元素:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    List<String> skippedNames = names.stream()
    	.skip(2)
    	.collect(Collectors.toList());
    skippedNames.forEach(System.out::println);
    
2.8 peek():
  • 对流中的每个元素执行一个操作,但不改变流本身。主要用于调试:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    names.stream()
         .peek(name -> System.out.println("Processing: " + name))
         .map(String::toUpperCase)
         .collect(Collectors.toList());
    names.forEach(System.out::println);
    
2.9 mapToDouble(), mapToInt(), mapToLong():
  • 将元素映射到特定原始类型的流:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    IntStream intStream = names.stream().mapToInt(String::length);
    intStream.forEach(System.out::println);
    

这些数值流(IntStreamLongStreamDoubleStream)提供了专门的数值聚合操作(如 sumaveragemaxmin 等),这些操作比通用的 Stream<T> 提供的操作更高效,因为它们可以直接在数值类型上操作,而无需进行装箱(boxing)和拆箱(unboxing)操作。

3、终止操作
3.1 forEach():
  • 对流中的每个元素执行给定的操作。

语法:forEach(Consumer<? super T> action)

  1. Consumer: 这是一个函数式接口,接受一个参数并返回 void。它代表了一个对单个元素执行的操作,例如打印元素、更新外部变量等。
  2. <? super T>: 这是 Java 泛型中的一个通配符用法,表示 Consumer 接口可以接受任何 T 类型或 T 的任何超类型的实例。这使得 forEach 方法能够应用于任何类型的流。
List<String> items = Arrays.asList("A", "B", "C");
items.stream().forEach(System.out::println); // 打印每个元素
3.2 count():
  • 返回流中元素的数量
List<String> items = Arrays.asList("A", "B", "C");
long count = items.stream().count(); // 计算元素数量
System.out.println(count);
3.3 reduce():
  • 使用给定的二元操作符将流中的元素归约到一个值。

语法:reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)

  1. identity:一个初始值,它是累积操作的起始值。对于某些类型的操作(如求和、求积等),这个初始值可以是0或1。
  2. accumulator:一个二元操作函数,它接受两个参数:一个是累积结果,另一个是集合中的当前元素。这个函数将这两个参数结合起来,生成一个新的累积结果。
  3. combiner:一个可选的二元操作符,用于并行处理时合并各个线程的结果。如果不提供这个参数,那么在并行处理时会使用 accumulator 作为合并操作。
OptionalInt reduced = numbers.stream().mapToInt(Integer::intValue).reduce((a, b) -> a + b);
reduced.ifPresent(System.out::println);

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.stream().reduce(0, Integer::max);
System.out.println("最大值: " + sum);


List<String> words = Arrays.asList("Java", "Stream", "API");
String result = words.parallelStream()
	.reduce("",
		(partialString, word) -> partialString + word,
		(left, right) -> left + right);
System.out.println("Result: " + result);
3.4 collect()
  • 将流中的元素汇总到一个集合或执行其他汇总操作。

语法:collect(Collector<? super T, A, R> collector)

  1. T:流中元素的类型。
  2. A:累加器的类型,用于累积流中的元素。
  3. R:结果的类型,即收集操作的最终输出。
1. 归集: toList(),toSet(),toMap()
  • 因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。 toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。
List<String> items = Arrays.asList("A", "B", "C", "C");
Set<String> set = items.stream().collect(Collectors.toSet()); // 收集到Set
System.out.println(set);

List<String> list = items.stream().collect(Collectors.toList()); // 收集到List
System.out.println(list);

Map<String, Integer> map = items.stream().collect(Collectors.toMap(
	String::toUpperCase, // 键
	String::length,       // 值
//   (oldValue, newValue) -> oldValue + newValue, // 合并函数(处理键值重复问题,将值进行合并)
	(existing, replacement) -> existing // 选择保留现有的值
));// 收集到map
System.out.println(map);
2. 计数: counting()
  • 统计流中元素的数量。
List<String> items = Arrays.asList("apple", "banana", "cherry");
long count = items.stream().collect(Collectors.counting());
System.out.println(count);
3. 平均值: averagingInt(), averagingLong(), averagingDouble()
  • 计算流中元素数值的平均值。

    语法:

    • Collectors.averagingInt(ToIntFunction<T> mapper)
    • Collectors.averagingLong(ToLongFunction<T> mapper)
    • Collectors.averagingDouble(ToDoubleFunction<T> mapper)

    ToDoubleFunction<T> mapper:这是一个函数式接口的参数,它指定了一个转换函数。这个转换函数接受流中元素的类型 T 作为输入,并返回一个 double 类型的值作为输出。这个 double 值随后会被用于计算。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double averagingDouble = numbers.stream().collect(Collectors.averagingDouble(n -> n));
double averagingInt = numbers.stream().collect(Collectors.averagingInt(n -> n));
double averagingLong = numbers.stream().collect(Collectors.averagingLong(n -> n));
System.out.println(averagingDouble);
System.out.println(averagingInt);
System.out.println(averagingLong);
4. 求和: summingInt(), summingLong(), summingDouble()
  • 对流中元素的数值属性进行求和。

    语法:

    • Collectors.summingInt(ToIntFunction<? super T> mapper)
    • Collectors.summingLong(ToIntFunction<? super T> mapper)
    • Collectors.summingDouble(ToIntFunction<? super T> mapper)

ToIntFunction<? super T> mapper:用于从类型为 T 或其父类型的流元素中提取出一个 int 类型的数值。? super T 表示该函数可以接受 T 类型或者 T 的任何父类型的对象作为输入参数 。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer summingInt = numbers.stream().collect(Collectors.summingInt(n -> n));
Long summingLong = numbers.stream().collect(Collectors.summingLong(n -> n));
Double summingDouble = numbers.stream().collect(Collectors.summingDouble(n -> n));
System.out.println(summingInt);
System.out.println(summingLong);
System.out.println(summingDouble);
5. 最值:maxBy(), minBy()
  • 找出流中元素的最大值或最小值。

    语法:

    • Collectors.maxBy(Comparator<? super T> comparator)

    • Collectors.minBy(Comparator<? super T> comparator)

      Comparator<? super T> comparator:这是一个函数式接口 Comparator 的实例,它定义了如何比较两个类型为 T 或其父类型的元素。? super T 表示比较器可以接受 T 类型或者 T 的任何父类型的对象作为输入参数。这个比较器用于确定流中元素的顺序,并找出最大值。

List<String> items = Arrays.asList("apple", "banana", "cherry");
Optional<String> maxLength = items.stream()
	.collect(Collectors.maxBy(Comparator.comparingInt(String::length))); // 最大值
Optional<String> minLength = items.stream()
	.collect(Collectors.minBy(Comparator.comparingInt(String::length))); // 最小值
maxLength.ifPresent(System.out::println); // "banana"
minLength.ifPresent(System.out::println); // "apple"
6. 统计以上所有:summarizingInt()、summarizingLong()、summarizingDouble()
  • 统计以上所有:生成统计信息,包括总和、平均值、最小值、最大值。。

    语法:

    • Collectors.summarizingInt(ToIntFunction<? super T> mapper)
    • Collectors.summarizingLong(ToIntFunction<? super T> mapper)
    • Collectors.summarizingDouble(ToIntFunction<? super T> mapper)

ToIntFunction<? super T> mapper:用于从类型为 T 或其父类型的流元素中提取出一个 int 类型的数值。? super T 表示该函数可以接受 T类型或者 T 的任何父类型的对象作为输入参数 。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(e -> e));
System.out.println(stats);
System.out.println("Count: " + stats.getCount());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
7. 连接:Joining()

将流中的元素连接成一个 String,可以指定分隔符、前缀和后缀。

List<String> parts = Arrays.asList("Hello", "world", "!");
String result = parts.stream().collect(Collectors.joining(", ", "[", "]"));
System.out.println(result);
8. 分组:groupingBy(),partitioningBy() 分区

groupingBy()

  • 功能:将流中的元素按照给定的分类函数(classifier function)进行分组。
  • 返回类型Map<K, List<T>>,其中 K 是分类键,T 是流中元素的类型。结果是一个以分类键为键,以相同键的元素列表为值的 Map
  • 用法:适用于需要根据某种属性对流中的元素进行分组的场景。

partitioningBy()

  • 功能:将流中的元素按照给定的谓词(predicate)进行二分分区,即根据谓词的结果(truefalse)来分组。
  • 返回类型Map<Boolean, List<T>>,其中 Boolean 是谓词的结果,T 是流中元素的类型。结果是一个以 truefalse 为键,以对应的元素列表为值的 Map
  • 用法:适用于需要将元素分为两个互补组的场景(例如,符合条件和不符合条件)。
// groupingBy()

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person {
    private String name;
    private int age;
    // 构造函数、getter和setter方法省略
}

@Test
void list() {
    List<Person> people = Arrays.asList(  
        new Person("Alice", 17),  
        new Person("Bob", 17),  
        new Person("Charlie", 20),  
        new Person("David", 25)  
    );  
    Map<Integer, List<Person>> byAge = people.stream()  
        .collect(Collectors.groupingBy(Person::getAge)); // 按照年龄进行分组
    System.out.println(byAge);
    
    Map<Boolean, List<Person>> adultsAndMinors = items.stream()
         .collect(Collectors.partitioningBy(p -> p.getAge() >= 18)); // 按照成年人未成年人进行分区
    System.out.println(adultsAndMinors);
}
3.5 min(),max()
  • min:返回流中按照给定比较器排序的最小元素。

语法:min(Comparator<? super T> comparator)

  • max:返回流中按照给定比较器排序的最大元素。

语法:max(Comparator<? super T> comparator)

List<Integer> items = Arrays.asList(1, 2, 3, 4);
Optional<Integer> min = items.stream().min(Comparator.naturalOrder()); // 找到最小元素
min.ifPresent(System.out::println);

Optional<Integer> max = items.stream().max(Comparator.naturalOrder()); // 找到最大元素
max.ifPresent(System.out::println);
3.6 anyMatch(), allMatch(), noneMatch()
  • anyMatch:如果流中的任何元素满足给定的条件,则返回 true

语法:anyMatch(Predicate<? super T> predicate)

  • allMatch:如果流中的所有元素都满足给定的条件,则返回 true

语法:allMatch(Predicate<? super T> predicate)

  • noneMatch:如果流中的没有任何元素满足给定的条件,则返回 true

语法:noneMatch(Predicate<? super T> predicate)

List<String> items = Arrays.asList("A", "B", "C");
boolean anyStartsWithA = items.stream().anyMatch(item -> item.startsWith("A")); // 检查是否有以"A"开头的元素
System.out.println(anyStartsWithA);

boolean allStartsWithA = items.stream().allMatch(item -> item.startsWith("A")); // 检查是否所有元素以"A"开头
System.out.println(allStartsWithA);

boolean noneStartsWithZ = items.stream().noneMatch(item -> item.startsWith("Z")); // 检查是否没有以"Z"开头的元素
System.out.println(noneStartsWithZ);
3.7 findFirst(), findAny()
  • findFirst:返回流中的第一个元素(按顺序)。

  • findAny:返回流中的任意元素(可以是并行流中的任意元素)。

List<String> items = Arrays.asList("A", "B", "C");
Optional<String> first = items.stream().findFirst(); // 获取第一个元素
first.ifPresent(System.out::println);

Optional<String> any = items.parallelStream().findAny(); // 获取任意元素
any.ifPresent(System.out::println);
3.8 toArray()
  • 将流中的元素收集到数组中。

    语法:toArray(IntFunction<T[]> generator

List<String> items = Arrays.asList("A", "B", "C");
String[] array = items.stream().toArray(String[]::new);
System.out.println("Array: " + Arrays.toString(array));
3.9 iterator()
  • 返回流的迭代器,允许逐个访问流中的元素。
List<String> items = Arrays.asList("A", "B", "C");
Iterator<String> iterator = items.stream().iterator();
while (iterator.hasNext()) {
	System.out.println(iterator.next());
}
4、并行流
  • 说明:

并行流是 Java 8 引入的 Stream API 的一个特性,它允许你利用多核处理器的计算能力,通过并行执行来加速对集合数据的操作。使用并行流可以提高性能,用于对集合进行处理。串行流是按顺序处理集合元素,而并行流则会将集合元素分成多个部分,并在多个线程上同时处理这些部分。 在某些情况下,并行流可能比串行流更高效,特别是在处理大量数据时。但是,并行流的效率也受到多种因素的影响,包括数据量大小、处理逻辑的复杂度、硬件资源等等。 通常情况下,并行流可以在多核处理器上更好地利用多线程处理数据,从而提高处理速度。但是,由于线程间的调度和同步开销,有时候并行流并不一定比串行流更快。

  • 注意事项

    • 线程安全:确保在并行流中使用的函数(如 mapfilter 中的 lambda 表达式)是线程安全的。

    • 状态维护:并行流中避免使用非线程安全的状态,如在 lambda 表达式中使用外部的非 final 变量。

    • 性能考量:并行流可能会引入线程管理的开销,对于小数据集,使用并行流可能反而比顺序流慢。

    • 顺序依赖:并行流不保证元素的处理顺序,如果顺序很重要,应该使用顺序流。

@Test
void list() {
    List<String> items = Arrays.asList("A", "B", "C");
    // 顺序流/串行流
    Stream<String> stream = items.stream();
    stream.forEach(System.out::print);
    System.out.println();
    // 方式一: 直接获取并行的Stream流
    Stream<String> stream1 = items.parallelStream();
    stream1.forEach(System.out::print);
    System.out.println();
    //方式二: 通过Stream的静态方法parallel()获取并行的Stream流
    Stream<String> stream3 = items.stream().parallel();
    stream3.forEach(System.out::print);
    
     // 顺序流计算
    long start = System.currentTimeMillis();
    int sum = IntStream.rangeClosed(1, 1000000000).sum();
    long end = System.currentTimeMillis();
    System.out.println("顺序流计算结果:" + sum + ",耗时:" + (end - start) + " 毫秒");

    // 并行流计算
    start = System.currentTimeMillis();
    sum = IntStream.rangeClosed(1, 1000000000).parallel().sum();
    end = System.currentTimeMillis();
    System.out.println("并行流计算结果:" + sum + ",耗时:" + (end - start) + " 毫秒");
}

二、实际使用

@Test
void stream() {
    List<String> items = Arrays.asList("A1", "B2", "C1", "C2");
    String string = items.stream().filter(name ->
            name.startsWith("C")
    ).collect(Collectors.joining(", ", "[", "]"));
    System.out.println(string);
}

感谢博主:https://blog.csdn.net/listeningsea/article/details/123141350

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值