java-函数式变成

Java 函数式编程之 Lambda 基础详解

引言

在 Java 开发中,单方法接口的匿名类实现常导致代码冗余。Java 8 引入的Lambda 表达式通过简化函数式接口的实现,让代码更简洁优雅。

一、Lambda 表达式基础语法

1. 本质与作用

  • 目标:替换单方法接口(如Comparator/Runnable)的匿名类实现
  • 核心思想:将函数逻辑直接作为 “参数” 传递,避免冗余的类定义

2. 语法结构

完整形式
(参数列表) -> { 
    方法体; 
    return 返回值; 
}

示例(传统匿名类 vs Lambda):

// 匿名类实现Comparator
Arrays.sort(array, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
});

// Lambda表达式
Arrays.sort(array, (s1, s2) -> {
    return s1.compareTo(s2);
});
简化形式

若方法体仅一行return语句,可省略大括号和return

Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));

3. 类型推断机制

  • 参数类型:编译器自动推断(如String类型可省略声明)
  • 返回值类型:根据方法逻辑自动推导(需与接口抽象方法返回值一致)

二、函数式接口(FunctionalInterface)

1. 定义与标注

  • 概念仅包含一个抽象方法的接口
  • 注解:推荐使用@FunctionalInterface显式标记(非强制,但可增强代码可读性)

2. 判断规则

  • 允许存在

    • default方法(接口默认实现)
    • static方法(属于接口本身)
    • Object继承的方法(如equals()不计入抽象方法)
  • 示例接口

    • Comparator(仅compare()为抽象方法)
    • Runnable(仅run()
    • Callable<V>(仅call()

3. 接口结构示例

@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2); // 唯一抽象方法
    default Comparator<T> reversed() { ... } // 允许的default方法
}

三、Lambda vs 匿名类对比

特性匿名类Lambda 表达式
代码量冗长(需声明类、方法、返回值)简洁(仅保留方法逻辑)
类型声明必须显式声明参数类型可省略(编译器推断)
适用场景所有接口(不限于单方法)仅适用于FunctionalInterface
可读性逻辑分散在类结构中聚焦核心业务逻辑

典型场景
当需要传递 “简单行为”(如排序规则、线程任务)时,Lambda 表达式优势显著。

四、实战练习:忽略大小写排序

需求:使用 Lambda 实现字符串数组的忽略大小写排序
代码实现

String[] array = {"Apple", "orange", "Banana"};
Arrays.sort(array, (s1, s2) -> s1.compareToIgnoreCase(s2));
System.out.println(Arrays.toString(array)); // 输出:[Apple, Banana, orange]

五、核心总结

  1. Lambda 表达式是 Java 函数式编程的核心特性,专门简化FunctionalInterface的实现
  2. 语法关键:参数列表->方法体,利用编译器推断减少样板代码
  3. 适用场景:所有单方法接口场景(如集合排序、多线程任务、事件监听)
  4. 最佳实践:配合@FunctionalInterface注解明确接口设计意图

Java 方法引用:静态、实例、构造方法引用详解

一、基本概念

定义

当函数式接口的方法签名与现有方法一致时,可直接引用该方法替代 Lambda 表达式,简化代码。
核心逻辑:方法签名需匹配函数式接口的抽象方法(参数类型、数量、返回类型一致,与方法名、类继承无关)。

二、方法引用类型与示例

1. 静态方法引用

  • 语法类名::静态方法名

  • 示例

    import java.util.Arrays;
    
    public class Main {
        public static void main(String[] args) {
            String[] array = {"Apple", "Orange", "Banana", "Lemon"};
            Arrays.sort(array, Main::cmp); // 引用静态方法cmp
            System.out.println(String.join(", ", array));
        }
    
        static int cmp(String s1, String s2) {
            return s1.compareTo(s2); // 签名与Comparator.compare一致
        }
    }
    

2. 实例方法引用

  • 语法实例对象::实例方法名 或 类名::实例方法名(实例类型作为首个参数)

  • 原理:实例方法隐含this参数,调用时this作为第一个参数传入。

  • 示例

    Arrays.sort(array, String::compareTo); 
    // 等价于 (s1, s2) -> s1.compareTo(s2),s1为隐含的this参数
    

3. 构造方法引用

  • 语法类名::new

  • 示例

    import java.util.stream.Collectors;
    
    List<String> names = List.of("Bob", "Alice", "Tim");
    List<Person> persons = names.stream()
        .map(Person::new) // 引用Person(String)构造方法,匹配Function<String, Person>
        .collect(Collectors.toList());
    
    class Person {
        String name;
        public Person(String name) { this.name = name; }
    }
    

三、关键要点

1. 方法签名匹配规则

  • 仅关注参数类型返回类型,不考虑方法名或类继承关系。
  • 示例:Comparator<String>.compare(String, String) 与 String.compareTo(String) 因参数和返回类型一致可匹配。

2. 实例方法的隐含参数

  • 实例方法引用时,调用对象(如String实例)作为第一个参数传入,等价于将实例方法视为 “扩展参数” 的静态方法。

3. 与 Lambda 的关系

  • 方法引用是 Lambda 的语法糖,适用于已有方法满足接口需求的场景,进一步简化代码。

🚀 Java Stream 深度解析:从基础概念到惰性计算实践

Java 8 引入的 Stream API 是函数式编程的核心特性之一,它通过流式操作简化集合处理,支持链式调用和惰性计算。

一、Stream 是什么?

1. 定义与本质

  • 所属包java.util.stream,与 java.io 流完全不同
  • 核心作用:处理 Java 对象序列 的内存计算,支持 有限 / 无限序列
  • 核心特性惰性计算(Lazy Evaluation),仅在需要结果时触发计算

2. 与其他数据结构的对比

特性java.io 流java.util.Listjava.util.stream
存储类型字节 / 字符序列内存中已存在的对象可能实时计算的对象
典型用途序列化 / 文件操作操作已存在的集合流式业务逻辑处理
元素数量限制有限有限可无限(惰性计算)

二、Stream 的核心特点:惰性计算

1. 什么是惰性计算?

  • 操作分类

    • 中间操作(如 map/filter/limit):仅定义规则,不触发计算
    • 终止操作(如 forEach/sum/collect):触发实际计算
  • 执行时机:直到调用终止操作时,才会按规则处理元素

2. 示例:无限序列的惰性处理

// 创建全体自然数的 Stream(未计算)
Stream<BigInteger> naturals = createNaturalStream(); 

// 转换为平方序列(仍未计算)
Stream<BigInteger> squares = naturals.map(n -> n.multiply(n)); 

// 截取前100个并打印(触发计算)
squares.limit(100).forEach(System.out::println);

关键点

  • 前两步仅定义转换规则,无实际计算
  • 最后一步 forEach 才驱动整个链条执行

三、Stream 核心方法实战

1. 转换操作(中间操作)

  • map(Function<T, R>) :将元素映射为新类型

    List<String> names = Arrays.asList("Alice", "Bob");
    names.stream()
         .map(String::toUpperCase) // 转换为大写
         .forEach(System.out::println); // 输出:ALICE, BOB
    
  • filter(Predicate<T>) :过滤元素

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
    numbers.stream()
           .filter(n -> n % 2 == 0) // 保留偶数
           .forEach(System.out::println); // 输出:2, 4
    
  • limit(long n) :截取前 n 个元素

2. 终止操作

  • forEach(Consumer<T>) :遍历元素

  • reduce() :聚合计算(如求和)

    int sum = numbers.stream().reduce(0, Integer::sum); // 计算总和
    
  • collect(Collectors.toList()) :转换为集合

四、为什么选择 Stream?

1. 优势场景

  • 复杂集合处理:链式操作替代多层循环
  • 大数据量处理:支持并行流(parallelStream()
  • 无限序列建模:如数学序列、数据流

2. 注意事项

  • 不修改原数据:Stream 操作返回新流,原集合不变
  • 一次性消费:流只能使用一次,重复调用需重新创建

Java Stream 创建方式全解析

导语

Java Stream 是函数式编程的核心工具,高效创建 Stream 是使用其强大操作(如 mapfilterreduce)的前提。

一、Stream.of():快速创建固定元素 Stream

适用场景:测试或临时创建已知元素的有限 Stream。
语法Stream.of(元素1, 元素2, ...)
示例代码

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("A", "B", "C", "D");
        stream.forEach(System.out::println); // 输出:A B C D
    }
}

特点:元素固定,直接传入可变参数,适合少量元素场景。

二、基于数组或 Collection:转换现有数据结构

适用场景:将数组或集合(List/Set/Queue)转换为 Stream 进行处理。

2.1 数组转换

语法Arrays.stream(数组)
示例代码

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

public class Main {
    public static void main(String[] args) {
        Stream<String> stream = Arrays.stream(new String[]{"X", "Y", "Z"});
        stream.forEach(System.out::println); // 输出:X Y Z
    }
}

2.2 Collection 转换

语法collection.stream()
示例代码

import java.util.List;

public class Main {
    public static void main(String[] args) {
        Stream<String> stream = List.of("Apple", "Banana").stream();
        stream.forEach(System.out::println); // 输出:Apple Banana
    }
}

特点:基于现有数据结构,元素与原数据一致,支持有限遍历。

三、基于 Supplier:创建无限序列 Stream

适用场景:生成动态、无限序列(如自然数、斐波那契数列)。
语法Stream.generate(Supplier<T> supplier)
核心逻辑:通过 Supplier.get() 方法实时计算元素,内存占用极低。
示例代码(生成自然数序列):

import java.util.function.Supplier;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream<Integer> natural = Stream.generate(new NaturalSupplier());
        natural.limit(20).forEach(System.out::println); // 输出 1-20
    }
}

class NaturalSupplier implements Supplier<Integer> {
    int n = 0;
    public Integer get() {
        n++;
        return n;
    }
}

注意:无限序列必须通过 limit()findFirst() 等方法转为有限序列,否则会导致死循环!

四、其他 API 方法:文件、字符串分割等

4.1 文件逐行转换(Files.lines()

适用场景:按行读取文本文件。
示例代码

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) throws Exception {
        try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
            lines.forEach(System.out::println); // 逐行输出文件内容
        }
    }
}

4.2 正则表达式分割(Pattern.splitAsStream()

适用场景:将字符串按正则规则分割为 Stream。
示例代码

import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("\s+");
        Stream<String> words = p.splitAsStream("Hello world Java");
        words.forEach(System.out::println); // 输出:Hello world Java
    }
}

五、基本类型 Stream:IntStream/LongStream/DoubleStream

背景:Java 泛型不支持基本类型,装箱拆箱影响性能。
解决方案:使用专用基本类型 Stream:

  • 数组转换IntStream is = Arrays.stream(new int[]{1, 2, 3});
  • 包装类转换LongStream ls = list.stream().mapToLong(Long::parseLong);
    优势:避免装箱拆箱开销,直接操作基本类型。

总结:5 大创建方式速查表

创建方式核心方法 / API适用场景是否有限
固定元素Stream.of()测试、少量已知元素
数组 / 集合转换Arrays.stream()/ collection.stream()处理现有数据结构
无限序列Stream.generate(Supplier)动态生成、无限数据(需limit
文件 / 字符串分割Files.lines()/ Pattern.splitAsStream()文本处理、正则分割
基本类型IntStream/LongStream避免装箱拆箱,提升性能是 / 否

Java Stream.map () 用法详解:轻松实现流元素映射转换

一、引言

Stream.map() 是 Java 中 Stream 接口最常用的转换方法之一,用于将一个 Stream 的每个元素映射成另一个元素,并生成一个新的 Stream

二、map () 的核心作用

  • 本质:将指定函数应用于流的每个元素,实现元素类型转换数据处理
  • 核心逻辑:对输入流中的每个元素 x,通过函数 f(x) 转换为输出流中的元素 f(x),形成一一映射关系。

示例图解

输入流 [1, 2, 3, 4, 5] → 应用函数 f(x)=x² → 输出流 [1, 4, 9, 16, 25]

三、原理:Function 接口与类型转换

map() 方法接收一个 Function 接口对象作为参数,该接口定义了 apply(T t) 方法,用于将 T 类型转换为 R 类型。

方法签名

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

Function 接口定义

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t); // 将 T 转换为 R
}

关键特性

  • 支持 Lambda 表达式或方法引用简化代码。
  • 可实现任意类型转换(如 String → LocalDateInteger → String 等)。

四、实战示例

示例 1:数学计算(元素平方)

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);
        Stream<Integer> squares = numbers.map(n -> n * n); // 映射为平方数
        squares.forEach(System.out::println); // 输出:1 4 9 16 25
    }
}

示例 2:字符串处理(去空格 + 转小写)

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List.of("  Apple ", " pear ", " ORANGE", " BaNaNa ")
                .stream()
                .map(String::trim) // 去除首尾空格
                .map(String::toLowerCase) // 转小写
                .forEach(System.out::println); 
        // 输出:apple pear orange banana
    }
}

Java Stream.filter () 用法详解:高效过滤流元素的核心方法

导语

在 Java 函数式编程中,Stream.filter() 是Stream API 中用于数据过滤的核心转换方法。

一、filter () 核心概念

作用

  • Stream 中的每个元素执行条件测试
  • 过滤掉不满足条件的元素,保留符合条件的元素
  • 生成一个新的 Stream(元素数量可能减少)

核心原理

  • 接收一个Predicate 函数式接口作为参数
  • 遍历流中的每个元素,执行Predicate.test(T t) 判断
  • 符合条件的元素组成新流,不符合的被 "滤除"

二、使用方法与示例

基础用法:过滤数值流

需求:从整数流中过滤出所有奇数

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
                // 过滤条件:n是奇数
                .filter(n -> n % 2 != 0) 
                .forEach(System.out::println); // 输出:1 3 5 7 9
    }
}

进阶用法:过滤对象流

需求:从日期流中过滤出所有周末(周六 / 周日)

import java.time.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        // 生成2020年1月的日期流
        Stream.generate(new LocalDateSupplier())
                .limit(31)
                // 过滤条件:是周六或周日
                .filter(ldt -> ldt.getDayOfWeek() == DayOfWeek.SATURDAY 
                             || ldt.getDayOfWeek() == DayOfWeek.SUNDAY)
                .forEach(System.out::println); // 输出所有周末日期
    }
}

// 日期生成器
class LocalDateSupplier implements Supplier<LocalDate> {
    LocalDate start = LocalDate.of(2020, 1, 1);
    int n = -1;
    public LocalDate get() {
        n++;
        return start.plusDays(n);
    }
}

三、关键接口:Predicate

定义

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t); // 判断元素t是否符合条件
}

使用场景

  • 自定义复杂过滤逻辑
  • 支持方法引用和 Lambda 表达式
  • 可与and()or()negate() 组合使用

Java Stream 中的 reduce 方法详解:从基础用法到对象聚合

导语

在 Java 的 Stream 操作中,map()filter()属于转换方法,而reduce()是重要的聚合方法,用于将流中的所有元素按照指定规则聚合成一个结果。

一、reduce 基础用法:带初始值的聚合

reduce()最常用的形式是传入初始值BinaryOperator函数,该函数定义了元素与累加结果的聚合逻辑。

示例 1:求和

import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        // 初始值为0,累加逻辑为acc + n
        int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
                        .reduce(0, (acc, n) -> acc + n);
        System.out.println(sum); // 输出:45
    }
}

执行过程

  1. 初始值acc=0
  2. 依次对每个元素执行acc = acc + n,最终返回累加结果。

示例 2:求积

int product = Stream.of(1, 2, 3, 4, 5)
                    .reduce(1, (acc, n) -> acc * n); // 初始值必须为1
System.out.println(product); // 输出:120

二、无初始值:返回 Optional 对象

若不传入初始值,reduce()会返回Optional类型,以处理流中元素可能为 0 的情况(避免空指针异常)。

Stream<Integer> stream = Stream.of(1, 2, 3);
Optional<Integer> optSum = stream.reduce((acc, n) -> acc + n);
optSum.ifPresent(result -> System.out.println("结果:" + result)); // 输出:6

注意:若流为空,Optional将返回空值,需通过isPresent()ifPresent()判断。

三、对象聚合:将配置行转换为 Map

reduce()不仅适用于数值计算,还可用于聚合 Java 对象。以下示例将配置文件的每行字符串转换为Map<String, String>

import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<String> props = List.of("profile=native", "debug=true", "logging=warn");
        
        Map<String, String> config = props.stream()
            // 第一步:将每个字符串映射为单个键值对Map
            .map(kv -> {
                String[] arr = kv.split("=", 2);
                return Map.of(arr[0], arr[1]); // Java 9+可用Map.of
            })
            // 第二步:将所有小Map合并为一个大Map
            .reduce(new HashMap<>(), (m, kv) -> {
                m.putAll(kv);
                return m;
            });
        
        config.forEach((k, v) -> System.out.println(k + "=" + v));
    }
}

输出结果

profile=native
debug=true
logging=warn

四、核心原理与注意事项

  1. BinaryOperator接口
    定义为T apply(T t, T u),用于接收前一次结果acc和当前元素n,返回新的累加结果。

  2. 流的一次性特性
    流中的元素只能被操作一次,聚合操作(如reduce)会触发流的遍历,后续无法重复使用该流。

  3. 初始值的作用

    • 作为聚合的起点(如求和用0,求积用1)。
    • 决定返回值类型(带初始值返回具体类型,不带则返回Optional)。

Java Stream 输出集合:从转换到聚合的完整实践

引言

在 Java 中使用 Stream 时,操作可分为两类:

  • 转换操作(如 map()filter()):仅定义规则,不触发实际计算,返回新的 Stream
  • 聚合操作(如 reduce()collect()):触发链式计算,返回具体结果或集合。

一、输出为 List

核心方法collect(Collectors.toList())
作用:过滤元素后收集到 List 中。
示例

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        // 原始 Stream(包含空字符串、null)
        Stream<String> stream = Stream.of("Apple", "", null, "Pear", "  ", "Orange");
        // 过滤非空字符串并收集到 List
        List<String> list = stream
                .filter(s -> s != null && !s.isBlank()) // 过滤条件
                .collect(Collectors.toList()); // 收集为 List
        System.out.println(list); // 输出:[Apple, Pear, Orange]
    }
}

二、输出为数组

核心方法toArray(数组构造方法)
作用:将 Stream 元素转为指定类型数组。
示例

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Apple", "Banana", "Orange");
        // 转为 String 数组
        String[] array = list.stream()
                .toArray(String[]::new); // 传入数组构造方法
        System.out.println(Arrays.toString(array)); // 输出:[Apple, Banana, Orange]
    }
}

三、输出为 Map

核心方法collect(Collectors.toMap(keyMapper, valueMapper))
作用:将元素映射为 key-value 对存入 Map
示例

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
        // 按冒号分割字符串,前半部分为 key,后半部分为 value
        Map<String, String> map = stream.collect(Collectors.toMap(
                s -> s.substring(0, s.indexOf(':')), // key 映射
                s -> s.substring(s.indexOf(':') + 1) // value 映射
        ));
        System.out.println(map); // 输出:{APPL=Apple, MSFT=Microsoft}
    }
}

四、分组输出

核心方法collect(Collectors.groupingBy(分组键映射, 收集器))
作用:按指定规则分组,每组元素存入 List 或其他集合。
示例:按字符串首字母分组:

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots");
        // 按首字母分组,结果为 Map<String, List<String>>
        Map<String, List<String>> groups = list.stream()
                .collect(Collectors.groupingBy(
                        s -> s.substring(0, 1), // 分组键:首字母
                        Collectors.toList() // 每组收集为 List
                ));
        System.out.println(groups);
        /* 输出:
        {
            A=[Apple, Avocado, Apricots],
            B=[Banana, Blackberry],
            C=[Coconut, Cherry]
        }
        */
    }
}

Java Stream 高级操作详解:排序、去重、合并与并行处理

导语

Java Stream 提供了丰富的操作方法,除基础的 mapfilter 外,其高级操作如排序、去重、合并等能高效处理集合数据。

一、排序操作(sorted()

1. 自然排序

需元素实现 Comparable 接口,直接调用 sorted()

List<String> list = List.of("Orange", "apple", "Banana")
    .stream()
    .sorted()
    .collect(Collectors.toList()); // [Banana, Orange, apple]

2. 自定义排序

通过 Comparator 定制排序规则:

List<String> list = List.of("Orange", "apple", "Banana")
    .stream()
    .sorted(String::compareToIgnoreCase) // 忽略大小写排序
    .collect(Collectors.toList()); // [apple, Banana, Orange]

注意sorted() 是转换操作,返回新 Stream

二、去重操作(distinct()

基于元素的 equals() 方法去重,直接调用 distinct()

List.of("A", "B", "A", "C", "B", "D")
    .stream()
    .distinct()
    .collect(Collectors.toList()); // [A, B, C, D]

三、截取操作(skip()/limit()

  • skip(n):跳过前 n 个元素
  • limit(n):保留前 n 个元素
    示例
List.of("A", "B", "C", "D", "E", "F")
    .stream()
    .skip(2) // 跳过 A、B
    .limit(3) // 截取 C、D、E
    .collect(Collectors.toList()); // [C, D, E]

四、合并操作(concat()/flatMap()

1. 简单合并(concat()

合并两个 Stream

Stream<String> s1 = List.of("A", "B", "C").stream();
Stream<String> s2 = List.of("D", "E").stream();
Stream.concat(s1, s2).collect(Collectors.toList()); // [A, B, C, D, E]

2. 深度合并(flatMap()

将 Stream 中的嵌套集合展开为单一 Stream

Stream<List<Integer>> nestedList = Stream.of(
    Arrays.asList(1, 2, 3),
    Arrays.asList(4, 5, 6)
);
Stream<Integer> flatList = nestedList.flatMap(list -> list.stream()); // 1,2,3,4,5,6

五、并行处理(parallel()

通过 parallel() 将 Stream 转为并行流,自动利用多线程加速处理(适用于大数据集):

String[] result = Stream.of("a", "b", "c", "d")
    .parallel() // 并行处理
    .sorted()
    .toArray(String[]::new);

六、聚合与匹配操作

1. 聚合方法

  • count():统计元素个数
  • max(Comparator)/min(Comparator):求最值
  • sum()/average():数值流求和、平均值(仅适用于 IntStream/LongStream/DoubleStream示例
IntStream.of(1, 2, 3, 4, 5)
    .sum(); // 15
DoubleStream.of(1.1, 2.2, 3.3)
    .average(); // OptionalDouble[2.2]

2. 匹配方法

  • allMatch(Predicate):所有元素满足条件返回 true
  • anyMatch(Predicate):至少一个元素满足条件返回 true
boolean allEven = IntStream.of(2, 4, 6).allMatch(n -> n % 2 == 0); // true
boolean hasEven = IntStream.of(1, 3, 5).anyMatch(n -> n % 2 == 0); // false

3. 遍历操作(forEach()

终端操作,遍历元素执行消费逻辑:

Stream.of("apple", "banana")
    .forEach(System.out::println); // 输出每个元素

七、操作分类小结

操作类型具体方法
转换操作mapfiltersorteddistinctskiplimit
合并操作concatflatMap
并行处理parallel
聚合操作reducecollectcountmaxminsumaverage
其他操作allMatchanyMatchforEach