04-Java语言核心-语法特性-Lambda与函数式接口详解

7 阅读23分钟

Lambda与函数式接口详解

一、知识概述

Lambda表达式是Java 8引入的最重要特性之一,它让Java具备了函数式编程的能力。Lambda表达式可以简化代码、提高可读性,特别是在处理集合操作时,配合Stream API可以实现声明式编程。

什么是函数式编程?

函数式编程是一种编程范式,它将计算视为函数求值,强调:

  • 不可变性:数据一旦创建就不再改变
  • 纯函数:相同输入总是产生相同输出,无副作用
  • 高阶函数:函数可以作为参数传递,也可以作为返回值
  • 函数组合:将简单函数组合成复杂函数

Lambda表达式的优势

对比项传统方式Lambda方式
代码行数多(匿名内部类)少(简洁表达式)
可读性较差(样板代码多)好(意图清晰)
并行处理手动实现Stream API自动
代码复用接口+实现类方法引用直接复用

二、知识点详细讲解

2.1 Lambda表达式基础

语法格式
// 完整格式
(参数类型 参数名) -> { 方法体 }

// 简化格式
(参数名) -> { 方法体 }
参数名 -> 方法体
参数名 -> 表达式
基础示例
import java.util.*;
import java.util.function.*;

/**
 * Lambda表达式基础语法
 */
public class LambdaBasicDemo {
    public static void main(String[] args) {
        
        // === 无参数、无返回值 ===
        // 传统方式
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello, World!");
            }
        };
        
        // Lambda方式
        Runnable r2 = () -> System.out.println("Hello, Lambda!");
        
        // 多行语句需要花括号
        Runnable r3 = () -> {
            System.out.println("Line 1");
            System.out.println("Line 2");
        };
        
        r1.run();
        r2.run();
        r3.run();
        
        // === 无参数、有返回值 ===
        // 传统方式
        Supplier<String> s1 = new Supplier<String>() {
            @Override
            public String get() {
                return "Hello, Supplier!";
            }
        };
        
        // Lambda方式
        Supplier<String> s2 = () -> "Hello, Lambda Supplier!";
        Supplier<String> s3 = () -> {
            String prefix = "Hello, ";
            return prefix + "Multi-line Lambda!";
        };
        
        System.out.println(s1.get());
        System.out.println(s2.get());
        System.out.println(s3.get());
        
        // === 一个参数、无返回值 ===
        // 传统方式
        Consumer<String> c1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("Consumed: " + s);
            }
        };
        
        // Lambda方式(参数类型可省略)
        Consumer<String> c2 = (s) -> System.out.println("Consumed: " + s);
        // 单参数可省略括号
        Consumer<String> c3 = s -> System.out.println("Consumed: " + s);
        
        c1.accept("Traditional");
        c2.accept("Lambda");
        c3.accept("Simplified");
        
        // === 一个参数、有返回值 ===
        // 传统方式
        Function<String, Integer> f1 = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        };
        
        // Lambda方式
        Function<String, Integer> f2 = s -> s.length();
        Function<String, Integer> f3 = String::length; // 方法引用
        
        System.out.println("Length: " + f1.apply("Hello"));
        System.out.println("Length: " + f2.apply("Lambda"));
        System.out.println("Length: " + f3.apply("Method Reference"));
        
        // === 两个参数、无返回值 ===
        BiConsumer<String, Integer> bc1 = (name, age) -> 
            System.out.println(name + " is " + age + " years old");
        bc1.accept("张三", 25);
        
        // === 两个参数、有返回值 ===
        BiFunction<Integer, Integer, Integer> bf1 = (a, b) -> a + b;
        BiFunction<Integer, Integer, Integer> bf2 = (a, b) -> {
            int sum = a + b;
            return sum * 2;
        };
        
        System.out.println("Sum: " + bf1.apply(10, 20));
        System.out.println("Double Sum: " + bf2.apply(10, 20));
        
        // === 指定参数类型 ===
        BiFunction<Integer, String, String> typed = (Integer num, String str) -> 
            str + num;
        System.out.println(typed.apply(100, "ID-"));
    }
}

2.2 函数式接口

函数式接口是只有一个抽象方法的接口,可以使用@FunctionalInterface注解标注。

四大核心函数式接口
import java.util.function.*;

/**
 * Java 8 四大核心函数式接口
 */
public class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        
        // === 1. Consumer<T>:消费型接口 ===
        // void accept(T t)
        System.out.println("=== Consumer<T> ===");
        
        Consumer<String> printConsumer = s -> System.out.println("打印: " + s);
        printConsumer.accept("Hello Consumer");
        
        // 链式消费
        Consumer<String> upperConsumer = s -> System.out.println("大写: " + s.toUpperCase());
        Consumer<String> lowerConsumer = s -> System.out.println("小写: " + s.toLowerCase());
        
        printConsumer.andThen(upperConsumer).andThen(lowerConsumer).accept("Test");
        
        // === 2. Supplier<T>:供给型接口 ===
        // T get()
        System.out.println("\n=== Supplier<T> ===");
        
        Supplier<String> uuidSupplier = () -> UUID.randomUUID().toString();
        System.out.println("UUID: " + uuidSupplier.get());
        
        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        System.out.println("Random: " + randomSupplier.get());
        
        // 工厂模式
        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
        list.add("Item");
        System.out.println("List: " + list);
        
        // === 3. Function<T, R>:函数型接口 ===
        // R apply(T t)
        System.out.println("\n=== Function<T, R> ===");
        
        Function<String, Integer> lengthFunc = String::length;
        System.out.println("Length: " + lengthFunc.apply("Hello"));
        
        Function<Integer, String> intToStr = Object::toString;
        System.out.println("String: " + intToStr.apply(123));
        
        // 组合函数
        Function<String, String> upper = String::toUpperCase;
        Function<String, String> addPrefix = s -> "PREFIX-" + s;
        Function<String, String> addSuffix = s -> s + "-SUFFIX";
        
        // 先执行upper,再执行addPrefix
        Function<String, String> composed = addPrefix.compose(upper);
        System.out.println("Composed: " + composed.apply("hello")); // PREFIX-HELLO
        
        // 先执行upper,再执行addSuffix
        Function<String, String> andThen = upper.andThen(addSuffix);
        System.out.println("AndThen: " + andThen.apply("hello")); // HELLO-SUFFIX
        
        // === 4. Predicate<T>:断言型接口 ===
        // boolean test(T t)
        System.out.println("\n=== Predicate<T> ===");
        
        Predicate<Integer> isPositive = n -> n > 0;
        System.out.println("5 > 0: " + isPositive.test(5));
        System.out.println("-1 > 0: " + isPositive.test(-1));
        
        // 组合断言
        Predicate<Integer> isEven = n -> n % 2 == 0;
        Predicate<Integer> isGreaterThan10 = n -> n > 10;
        
        // 与(and)
        Predicate<Integer> isEvenAndGreater10 = isEven.and(isGreaterThan10);
        System.out.println("12 is even and > 10: " + isEvenAndGreater10.test(12)); // true
        System.out.println("8 is even and > 10: " + isEvenAndGreater10.test(8));   // false
        
        // 或(or)
        Predicate<Integer> isEvenOrGreater10 = isEven.or(isGreaterThan10);
        System.out.println("15 is even or > 10: " + isEvenOrGreater10.test(15)); // true
        
        // 非(negate)
        Predicate<Integer> isNotPositive = isPositive.negate();
        System.out.println("-5 is not positive: " + isNotPositive.test(-5)); // true
        
        // isEqual
        Predicate<String> isEqualToHello = Predicate.isEqual("Hello");
        System.out.println("Is 'Hello': " + isEqualToHello.test("Hello")); // true
    }
}
其他常用函数式接口
import java.util.function.*;

/**
 * 其他常用函数式接口
 */
public class MoreFunctionalInterfaces {
    public static void main(String[] args) {
        
        // === 1. BiFunction<T, U, R>:双参数函数 ===
        BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
        BiFunction<String, String, String> concat = (a, b) -> a + b;
        System.out.println("10 + 20 = " + add.apply(10, 20));
        System.out.println("Hello + World = " + concat.apply("Hello", "World"));
        
        // === 2. BiConsumer<T, U>:双参数消费者 ===
        BiConsumer<String, Integer> printNameAge = (name, age) -> 
            System.out.println(name + ": " + age + "岁");
        printNameAge.accept("张三", 25);
        
        // === 3. BiPredicate<T, U>:双参数断言 ===
        BiPredicate<String, Integer> checkLength = (s, len) -> s.length() == len;
        System.out.println("'Hello' length == 5: " + checkLength.test("Hello", 5));
        
        // === 4. UnaryOperator<T>:一元操作(输入输出同类型)===
        UnaryOperator<Integer> square = x -> x * x;
        UnaryOperator<String> toUpper = String::toUpperCase;
        System.out.println("5^2 = " + square.apply(5));
        System.out.println("hello -> " + toUpper.apply("hello"));
        
        // === 5. BinaryOperator<T>:二元操作(输入输出同类型)===
        BinaryOperator<Integer> sum = Integer::sum;
        BinaryOperator<String> join = (a, b) -> a + " " + b;
        System.out.println("1 + 2 = " + sum.apply(1, 2));
        System.out.println(join.apply("Hello", "World"));
        
        // === 6. 基本类型特化接口 ===
        // IntConsumer, LongConsumer, DoubleConsumer
        IntConsumer printInt = n -> System.out.println("Int: " + n);
        printInt.accept(100);
        
        // IntSupplier, LongSupplier, DoubleSupplier
        IntSupplier randomInt = () -> new Random().nextInt(100);
        System.out.println("Random int: " + randomInt.getAsInt());
        
        // IntFunction, LongFunction, DoubleFunction
        IntFunction<String> intToStr = n -> "Number: " + n;
        System.out.println(intToStr.apply(42));
        
        // IntPredicate, LongPredicate, DoublePredicate
        IntPredicate isPrime = n -> {
            if (n < 2) return false;
            for (int i = 2; i * i <= n; i++) {
                if (n % i == 0) return false;
            }
            return true;
        };
        System.out.println("17 is prime: " + isPrime.test(17));
        
        // IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
        IntUnaryOperator doubleIt = n -> n * 2;
        System.out.println("10 * 2 = " + doubleIt.applyAsInt(10));
        
        // IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
        IntBinaryOperator multiply = (a, b) -> a * b;
        System.out.println("6 * 7 = " + multiply.applyAsInt(6, 7));
        
        // IntToLongFunction, IntToDoubleFunction 等
        IntToLongFunction intToLong = n -> (long) n * 1000L;
        System.out.println("5 -> " + intToLong.applyAsLong(5));
        
        // === 7. ObjIntConsumer, ObjLongConsumer, ObjDoubleConsumer ===
        ObjIntConsumer<StringBuilder> appendInt = (sb, n) -> sb.append(n);
        StringBuilder sb = new StringBuilder("Numbers: ");
        appendInt.accept(sb, 123);
        System.out.println(sb);
    }
}

2.3 方法引用

方法引用是Lambda表达式的简写形式,当Lambda表达式只是调用一个已存在的方法时,可以使用方法引用。

四种方法引用类型
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

/**
 * 方法引用四种类型
 */
public class MethodReferenceDemo {
    
    // 静态方法
    public static int compareByName(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }
    
    public static void main(String[] args) {
        
        // === 1. 静态方法引用:类名::静态方法名 ===
        System.out.println("=== 静态方法引用 ===");
        
        // Lambda: (a, b) -> Math.max(a, b)
        // 方法引用: Math::max
        BinaryOperator<Integer> max1 = (a, b) -> Math.max(a, b);
        BinaryOperator<Integer> max2 = Math::max;
        System.out.println("Max: " + max2.apply(10, 20));
        
        // Lambda: s -> Integer.parseInt(s)
        // 方法引用: Integer::parseInt
        Function<String, Integer> parser1 = s -> Integer.parseInt(s);
        Function<String, Integer> parser2 = Integer::parseInt;
        System.out.println("Parse: " + parser2.apply("123"));
        
        // Lambda: s -> System.out.println(s)
        // 方法引用: System.out::println
        Consumer<String> printer = System.out::println;
        printer.accept("Hello Method Reference");
        
        // 自定义静态方法
        List<Person> people = Arrays.asList(
            new Person("张三", 25),
            new Person("李四", 30),
            new Person("王五", 20)
        );
        
        // Lambda: (a, b) -> compareByName(a, b)
        // 方法引用: MethodReferenceDemo::compareByName
        people.sort(MethodReferenceDemo::compareByName);
        System.out.println("Sorted by name: " + people);
        
        // === 2. 实例方法引用:对象::实例方法名 ===
        System.out.println("\n=== 实例方法引用 ===");
        
        // Lambda: s -> System.out.println(s)
        // 方法引用: System.out::println
        PrintStream out = System.out;
        Consumer<String> printToOut = out::println;
        printToOut.accept("Print via instance method reference");
        
        // Lambda: s -> list.add(s)
        // 方法引用: list::add
        List<String> list = new ArrayList<>();
        Consumer<String> adder = list::add;
        adder.accept("Item1");
        adder.accept("Item2");
        System.out.println("List: " + list);
        
        // Lambda: () -> "hello".length()
        // 方法引用: "hello"::length
        Supplier<Integer> lengthSupplier = "hello"::length;
        System.out.println("Length: " + lengthSupplier.get());
        
        // === 3. 类方法引用:类名::实例方法名 ===
        // 第一个参数作为方法调用者
        System.out.println("\n=== 类方法引用 ===");
        
        // Lambda: s -> s.length()
        // 方法引用: String::length
        // String是第一个参数的类型,调用该参数的length方法
        Function<String, Integer> lengthFunc = String::length;
        System.out.println("Length: " + lengthFunc.apply("Hello"));
        
        // Lambda: (s1, s2) -> s1.compareTo(s2)
        // 方法引用: String::compareTo
        BiFunction<String, String, Integer> compareFunc = String::compareTo;
        System.out.println("Compare: " + compareFunc.apply("abc", "abd"));
        
        // 集合排序
        List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
        // Lambda: (s1, s2) -> s1.compareToIgnoreCase(s2)
        // 方法引用: String::compareToIgnoreCase
        names.sort(String::compareToIgnoreCase);
        System.out.println("Sorted: " + names);
        
        // === 4. 构造方法引用:类名::new ===
        System.out.println("\n=== 构造方法引用 ===");
        
        // 无参构造
        // Lambda: () -> new ArrayList<String>()
        // 方法引用: ArrayList::new
        Supplier<ArrayList<String>> listSupplier = ArrayList::new;
        List<String> newList = listSupplier.get();
        System.out.println("New ArrayList: " + newList.getClass().getSimpleName());
        
        // 有参构造
        // Lambda: s -> new StringBuilder(s)
        // 方法引用: StringBuilder::new
        Function<String, StringBuilder> sbBuilder = StringBuilder::new;
        StringBuilder sb = sbBuilder.apply("Initial");
        System.out.println("StringBuilder: " + sb);
        
        // 数组构造引用
        // Lambda: n -> new String[n]
        // 方法引用: String[]::new
        IntFunction<String[]> arrayBuilder = String[]::new;
        String[] strArray = arrayBuilder.apply(5);
        System.out.println("Array length: " + strArray.length);
        
        // 在Stream中使用构造引用
        List<String> nameList = Arrays.asList("Alice", "Bob", "Charlie");
        List<Person> personList = nameList.stream()
            .map(Person::new)  // 构造引用
            .collect(Collectors.toList());
        System.out.println("Person list: " + personList);
        
        // === 5. 父类方法引用:super::方法名 ===
        System.out.println("\n=== 父类方法引用 ===");
        
        new Child().doSomething();
        
        // === 6. 当前对象方法引用:this::方法名 ===
        System.out.println("\n=== 当前对象方法引用 ===");
        
        new ThisDemo().processItems(Arrays.asList("A", "B", "C"));
    }
}

// 辅助类
class Person {
    private String name;
    private int age;
    
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }
    
    public Person(String name) {
        this.name = name;
        this.age = 18;
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() { return name; }
    public int getAge() { return age; }
    
    @Override
    public String toString() {
        return name + "(" + age + ")";
    }
}

// 父类
class Parent {
    public void print(String msg) {
        System.out.println("Parent: " + msg);
    }
}

// 子类
class Child extends Parent {
    @Override
    public void print(String msg) {
        System.out.println("Child: " + msg);
    }
    
    public void doSomething() {
        // 使用父类方法引用
        Consumer<String> parentPrinter = super::print;
        parentPrinter.accept("Hello from Child");
        
        // Lambda等价形式
        Consumer<String> lambdaPrinter = msg -> super.print(msg);
        lambdaPrinter.accept("Hello via Lambda");
    }
}

// this方法引用示例
class ThisDemo {
    public void processItem(String item) {
        System.out.println("Processing: " + item);
    }
    
    public void processItems(List<String> items) {
        // this::实例方法
        items.forEach(this::processItem);
        
        // Lambda等价形式
        items.forEach(item -> this.processItem(item));
    }
}

2.4 Stream API详解

Stream API是Java 8引入的函数式数据处理API,支持链式操作和并行处理。

Stream创建方式
import java.util.*;
import java.util.stream.*;

/**
 * Stream创建方式
 */
public class StreamCreationDemo {
    public static void main(String[] args) {
        
        // === 1. Collection转Stream ===
        System.out.println("=== Collection转Stream ===");
        List<String> list = Arrays.asList("A", "B", "C");
        Stream<String> streamFromList = list.stream();
        Stream<String> parallelStream = list.parallelStream();
        streamFromList.forEach(System.out::print);
        System.out.println();
        
        // === 2. 数组转Stream ===
        System.out.println("\n=== 数组转Stream ===");
        String[] array = {"X", "Y", "Z"};
        Stream<String> streamFromArray = Arrays.stream(array);
        streamFromArray.forEach(System.out::print);
        System.out.println();
        
        // 基本类型数组
        int[] intArray = {1, 2, 3, 4, 5};
        IntStream intStream = Arrays.stream(intArray);
        System.out.println("Sum: " + intStream.sum());
        
        // === 3. Stream静态方法 ===
        System.out.println("\n=== Stream静态方法 ===");
        
        // Stream.of()
        Stream<String> ofStream = Stream.of("A", "B", "C");
        ofStream.forEach(System.out::print);
        System.out.println();
        
        // Stream.empty()
        Stream<String> emptyStream = Stream.empty();
        System.out.println("Empty stream count: " + emptyStream.count());
        
        // Stream.generate() - 无限流
        Stream<Double> randomStream = Stream.generate(Math::random);
        randomStream.limit(5).forEach(n -> System.out.print(n + " "));
        System.out.println();
        
        // Stream.iterate() - 迭代流
        Stream<Integer> iterateStream = Stream.iterate(0, n -> n + 2);
        iterateStream.limit(5).forEach(n -> System.out.print(n + " ")); // 0 2 4 6 8
        System.out.println();
        
        // Java 9+ iterate带终止条件
        // Stream.iterate(0, n -> n < 10, n -> n + 1)
        
        // Stream.concat() - 连接流
        Stream<String> stream1 = Stream.of("A", "B");
        Stream<String> stream2 = Stream.of("C", "D");
        Stream<String> concatStream = Stream.concat(stream1, stream2);
        concatStream.forEach(System.out::print);
        System.out.println();
        
        // === 4. 基本类型Stream ===
        System.out.println("\n=== 基本类型Stream ===");
        
        // IntStream
        IntStream intStream1 = IntStream.range(1, 5);      // 1, 2, 3, 4
        IntStream intStream2 = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5
        System.out.print("range: ");
        intStream1.forEach(n -> System.out.print(n + " "));
        System.out.print("\nrangeClosed: ");
        intStream2.forEach(n -> System.out.print(n + " "));
        System.out.println();
        
        // LongStream
        LongStream longStream = LongStream.rangeClosed(1L, 5L);
        System.out.println("LongStream sum: " + longStream.sum());
        
        // DoubleStream
        DoubleStream doubleStream = DoubleStream.of(1.1, 2.2, 3.3);
        System.out.println("DoubleStream average: " + 
            doubleStream.average().orElse(0));
        
        // === 5. 文件行Stream ===
        System.out.println("\n=== 文件行Stream ===");
        // try (Stream<String> lines = Files.lines(Paths.get("test.txt"))) {
        //     lines.forEach(System.out::println);
        // }
        System.out.println("(Files.lines示例)");
        
        // === 6. 正则分割Stream ===
        System.out.println("\n=== 正则分割Stream ===");
        String text = "Hello,World,Java,Stream";
        Stream<String> words = Pattern.compile(",").splitAsStream(text);
        words.forEach(System.out::print);
        System.out.println();
    }
}
中间操作
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

/**
 * Stream中间操作
 */
public class StreamIntermediateDemo {
    public static void main(String[] args) {
        
        // === 1. filter:过滤 ===
        System.out.println("=== filter ===");
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        List<Integer> evens = numbers.stream()
            .filter(n -> n % 2 == 0)
            .collect(Collectors.toList());
        System.out.println("偶数: " + evens);
        
        // 多条件过滤
        List<Integer> filtered = numbers.stream()
            .filter(n -> n > 3)
            .filter(n -> n < 8)
            .collect(Collectors.toList());
        System.out.println("3 < n < 8: " + filtered);
        
        // === 2. map:映射 ===
        System.out.println("\n=== map ===");
        List<String> names = Arrays.asList("alice", "bob", "charlie");
        
        List<String> upperNames = names.stream()
            .map(String::toUpperCase)
            .collect(Collectors.toList());
        System.out.println("大写: " + upperNames);
        
        List<Integer> nameLengths = names.stream()
            .map(String::length)
            .collect(Collectors.toList());
        System.out.println("长度: " + nameLengths);
        
        // === 3. flatMap:扁平化映射 ===
        System.out.println("\n=== flatMap ===");
        List<List<Integer>> nestedList = Arrays.asList(
            Arrays.asList(1, 2),
            Arrays.asList(3, 4),
            Arrays.asList(5, 6)
        );
        
        // map返回Stream<Stream<Integer>>
        // flatMap返回Stream<Integer>
        List<Integer> flatList = nestedList.stream()
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
        System.out.println("扁平化: " + flatList);
        
        // 字符串拆分
        List<String> sentences = Arrays.asList("Hello World", "Java Stream");
        List<String> words = sentences.stream()
            .flatMap(s -> Arrays.stream(s.split(" ")))
            .collect(Collectors.toList());
        System.out.println("单词: " + words);
        
        // === 4. distinct:去重 ===
        System.out.println("\n=== distinct ===");
        List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3, 4);
        List<Integer> unique = duplicates.stream()
            .distinct()
            .collect(Collectors.toList());
        System.out.println("去重: " + unique);
        
        // === 5. sorted:排序 ===
        System.out.println("\n=== sorted ===");
        List<Integer> unsorted = Arrays.asList(5, 2, 8, 1, 9);
        
        // 自然排序
        List<Integer> sorted = unsorted.stream()
            .sorted()
            .collect(Collectors.toList());
        System.out.println("升序: " + sorted);
        
        // 自定义排序
        List<Integer> descSorted = unsorted.stream()
            .sorted(Comparator.reverseOrder())
            .collect(Collectors.toList());
        System.out.println("降序: " + descSorted);
        
        // 按属性排序
        List<Person> people = Arrays.asList(
            new Person("张三", 25),
            new Person("李四", 30),
            new Person("王五", 20)
        );
        
        List<Person> byAge = people.stream()
            .sorted(Comparator.comparing(Person::getAge))
            .collect(Collectors.toList());
        System.out.println("按年龄排序: " + byAge);
        
        // 多字段排序
        List<Person> complexSort = people.stream()
            .sorted(Comparator.comparing(Person::getAge)
                .reversed()
                .thenComparing(Person::getName))
            .collect(Collectors.toList());
        System.out.println("复杂排序: " + complexSort);
        
        // === 6. peek:查看元素(主要用于调试)===
        System.out.println("\n=== peek ===");
        List<Integer> peeked = numbers.stream()
            .peek(n -> System.out.println("处理前: " + n))
            .filter(n -> n > 5)
            .peek(n -> System.out.println("处理后: " + n))
            .collect(Collectors.toList());
        System.out.println("结果: " + peeked);
        
        // === 7. limit:限制数量 ===
        System.out.println("\n=== limit ===");
        List<Integer> limited = numbers.stream()
            .limit(5)
            .collect(Collectors.toList());
        System.out.println("前5个: " + limited);
        
        // === 8. skip:跳过元素 ===
        System.out.println("\n=== skip ===");
        List<Integer> skipped = numbers.stream()
            .skip(5)
            .collect(Collectors.toList());
        System.out.println("跳过前5个: " + skipped);
        
        // 分页
        int page = 2, pageSize = 3;
        List<Integer> page2 = numbers.stream()
            .skip((page - 1) * pageSize)
            .limit(pageSize)
            .collect(Collectors.toList());
        System.out.println("第2页: " + page2);
        
        // === 9. mapToInt/mapToLong/mapToDouble ===
        System.out.println("\n=== 基本类型映射 ===");
        int sum = people.stream()
            .mapToInt(Person::getAge)
            .sum();
        System.out.println("年龄总和: " + sum);
        
        double avgAge = people.stream()
            .mapToInt(Person::getAge)
            .average()
            .orElse(0);
        System.out.println("平均年龄: " + avgAge);
        
        // === 10. boxed:装箱 ===
        System.out.println("\n=== boxed ===");
        List<Integer> boxed = IntStream.range(1, 6)
            .boxed()
            .collect(Collectors.toList());
        System.out.println("装箱: " + boxed);
        
        // === 11. takeWhile/dropWhile (Java 9+) ===
        System.out.println("\n=== takeWhile/dropWhile ===");
        // takeWhile: 取元素直到条件不满足
        List<Integer> takeWhile = numbers.stream()
            .takeWhile(n -> n < 5)
            .collect(Collectors.toList());
        System.out.println("takeWhile(n < 5): " + takeWhile);
        
        // dropWhile: 丢弃元素直到条件不满足
        List<Integer> dropWhile = numbers.stream()
            .dropWhile(n -> n < 5)
            .collect(Collectors.toList());
        System.out.println("dropWhile(n < 5): " + dropWhile);
    }
}
终止操作
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

/**
 * Stream终止操作
 */
public class StreamTerminalDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
        
        // === 1. forEach/forEachOrdered ===
        System.out.println("=== forEach ===");
        numbers.stream()
            .filter(n -> n % 2 == 0)
            .forEach(n -> System.out.print(n + " "));
        System.out.println();
        
        // forEachOrdered保证顺序(即使是并行流)
        numbers.parallelStream()
            .forEachOrdered(n -> System.out.print(n + " "));
        System.out.println();
        
        // === 2. toArray ===
        System.out.println("\n=== toArray ===");
        String[] nameArray = names.stream().toArray(String[]::new);
        System.out.println("数组: " + Arrays.toString(nameArray));
        
        // === 3. reduce:归约 ===
        System.out.println("\n=== reduce ===");
        
        // 无初始值(返回Optional)
        Optional<Integer> sumOpt = numbers.stream()
            .reduce((a, b) -> a + b);
        System.out.println("求和: " + sumOpt.orElse(0));
        
        // 有初始值
        Integer sum = numbers.stream()
            .reduce(0, Integer::sum);
        System.out.println("求和(有初始值): " + sum);
        
        // 求最大值
        Optional<Integer> maxOpt = numbers.stream()
            .reduce(Integer::max);
        System.out.println("最大值: " + maxOpt.orElse(0));
        
        // 求最小值
        Optional<Integer> minOpt = numbers.stream()
            .reduce(Integer::min);
        System.out.println("最小值: " + minOpt.orElse(0));
        
        // 复杂归约
        // 计算字符串连接
        String concat = names.stream()
            .reduce("", (a, b) -> a + b + " ");
        System.out.println("连接: " + concat.trim());
        
        // 三参数reduce(支持并行)
        Integer parallelSum = numbers.parallelStream()
            .reduce(0, 
                (a, b) -> a + b,      // 累加器
                (a, b) -> a + b);     // 合并器
        System.out.println("并行求和: " + parallelSum);
        
        // === 4. collect:收集 ===
        System.out.println("\n=== collect ===");
        
        // 收集到List
        List<Integer> evenList = numbers.stream()
            .filter(n -> n % 2 == 0)
            .collect(Collectors.toList());
        System.out.println("偶数List: " + evenList);
        
        // 收集到Set
        Set<Integer> evenSet = numbers.stream()
            .filter(n -> n % 2 == 0)
            .collect(Collectors.toSet());
        System.out.println("偶数Set: " + evenSet);
        
        // 收集到指定集合
        LinkedList<Integer> linkedList = numbers.stream()
            .filter(n -> n > 5)
            .collect(Collectors.toCollection(LinkedList::new));
        System.out.println("LinkedList: " + linkedList);
        
        // 收集到Map
        Map<String, Integer> nameLengthMap = names.stream()
            .collect(Collectors.toMap(
                name -> name,           // key mapper
                String::length,         // value mapper
                (old, newVal) -> old    // merge function (处理key冲突)
            ));
        System.out.println("名字长度Map: " + nameLengthMap);
        
        // === 5. 分组 ===
        System.out.println("\n=== 分组 ===");
        List<Person> people = Arrays.asList(
            new Person("张三", 25),
            new Person("李四", 25),
            new Person("王五", 30),
            new Person("赵六", 30),
            new Person("钱七", 35)
        );
        
        // 按年龄分组
        Map<Integer, List<Person>> byAge = people.stream()
            .collect(Collectors.groupingBy(Person::getAge));
        System.out.println("按年龄分组: " + byAge);
        
        // 分组计数
        Map<Integer, Long> countByAge = people.stream()
            .collect(Collectors.groupingBy(
                Person::getAge,
                Collectors.counting()
            ));
        System.out.println("分组计数: " + countByAge);
        
        // 分组后取最大
        Map<Integer, Optional<Person>> oldestByAge = people.stream()
            .collect(Collectors.groupingBy(
                Person::getAge,
                Collectors.maxBy(Comparator.comparing(Person::getName))
            ));
        System.out.println("每组最大: " + oldestByAge);
        
        // 多级分组
        Map<Integer, Map<String, List<Person>>> multiLevel = people.stream()
            .collect(Collectors.groupingBy(
                Person::getAge,
                Collectors.groupingBy(p -> p.getName().startsWith("张") ? "张姓" : "其他")
            ));
        System.out.println("多级分组: " + multiLevel);
        
        // === 6. 分区 ===
        System.out.println("\n=== 分区 ===");
        Map<Boolean, List<Integer>> partitioned = numbers.stream()
            .collect(Collectors.partitioningBy(n -> n % 2 == 0));
        System.out.println("奇偶分区: " + partitioned);
        
        // 分区后统计
        Map<Boolean, Long> partitionCount = numbers.stream()
            .collect(Collectors.partitioningBy(
                n -> n % 2 == 0,
                Collectors.counting()
            ));
        System.out.println("分区计数: " + partitionCount);
        
        // === 7. joining:连接字符串 ===
        System.out.println("\n=== joining ===");
        String joined = names.stream()
            .collect(Collectors.joining());
        System.out.println("直接连接: " + joined);
        
        String joinedWithDelimiter = names.stream()
            .collect(Collectors.joining(", "));
        System.out.println("逗号连接: " + joinedWithDelimiter);
        
        String joinedWithWrapper = names.stream()
            .collect(Collectors.joining(", ", "[", "]"));
        System.out.println("带包装: " + joinedWithWrapper);
        
        // === 8. 统计 ===
        System.out.println("\n=== 统计 ===");
        IntSummaryStatistics stats = numbers.stream()
            .collect(Collectors.summarizingInt(Integer::intValue));
        System.out.println("统计信息:");
        System.out.println("  数量: " + stats.getCount());
        System.out.println("  总和: " + stats.getSum());
        System.out.println("  平均值: " + stats.getAverage());
        System.out.println("  最大值: " + stats.getMax());
        System.out.println("  最小值: " + stats.getMin());
        
        // 单独统计
        long count = numbers.stream().collect(Collectors.counting());
        int sum2 = numbers.stream().collect(Collectors.summingInt(Integer::intValue));
        double avg = numbers.stream().collect(Collectors.averagingInt(Integer::intValue));
        Optional<Integer> max = numbers.stream().collect(Collectors.maxBy(Integer::compare));
        Optional<Integer> min = numbers.stream().collect(Collectors.minBy(Integer::compare));
        
        // === 9. min/max ===
        System.out.println("\n=== min/max ===");
        Optional<Integer> maxValue = numbers.stream()
            .max(Integer::compare);
        System.out.println("最大值: " + maxValue.orElse(0));
        
        Optional<String> longestName = names.stream()
            .max(Comparator.comparing(String::length));
        System.out.println("最长名字: " + longestName.orElse(""));
        
        // === 10. count ===
        System.out.println("\n=== count ===");
        long evenCount = numbers.stream()
            .filter(n -> n % 2 == 0)
            .count();
        System.out.println("偶数个数: " + evenCount);
        
        // === 11. anyMatch/allMatch/noneMatch ===
        System.out.println("\n=== 匹配操作 ===");
        
        // anyMatch: 是否存在满足条件的元素
        boolean hasEven = numbers.stream()
            .anyMatch(n -> n % 2 == 0);
        System.out.println("存在偶数: " + hasEven);
        
        // allMatch: 所有元素是否都满足条件
        boolean allPositive = numbers.stream()
            .allMatch(n -> n > 0);
        System.out.println("全是正数: " + allPositive);
        
        // noneMatch: 是否没有满足条件的元素
        boolean noNegative = numbers.stream()
            .noneMatch(n -> n < 0);
        System.out.println("没有负数: " + noNegative);
        
        // === 12. findFirst/findAny ===
        System.out.println("\n=== 查找操作 ===");
        
        // findFirst: 找到第一个元素
        Optional<Integer> firstEven = numbers.stream()
            .filter(n -> n % 2 == 0)
            .findFirst();
        System.out.println("第一个偶数: " + firstEven.orElse(0));
        
        // findAny: 找到任意一个元素(并行流中更高效)
        Optional<Integer> anyEven = numbers.parallelStream()
            .filter(n -> n % 2 == 0)
            .findAny();
        System.out.println("任意偶数: " + anyEven.orElse(0));
    }
}

2.5 Optional类

Optional类是一个容器类,用于避免NullPointerException。

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

/**
 * Optional类详解
 */
public class OptionalDemo {
    public static void main(String[] args) {
        
        // === 1. 创建Optional ===
        System.out.println("=== 创建Optional ===");
        
        // Optional.of() - 非null值
        Optional<String> opt1 = Optional.of("Hello");
        System.out.println("of: " + opt1);
        
        // Optional.ofNullable() - 可能为null
        String nullable = Math.random() > 0.5 ? "World" : null;
        Optional<String> opt2 = Optional.ofNullable(nullable);
        System.out.println("ofNullable: " + opt2);
        
        // Optional.empty() - 空Optional
        Optional<String> opt3 = Optional.empty();
        System.out.println("empty: " + opt3);
        
        // === 2. 获取值 ===
        System.out.println("\n=== 获取值 ===");
        
        // get() - 不推荐,可能抛异常
        try {
            String value = opt1.get();
            System.out.println("get: " + value);
        } catch (NoSuchElementException e) {
            System.out.println("No value present");
        }
        
        // orElse() - 有值返回,无值返回默认值
        String val1 = opt2.orElse("默认值");
        System.out.println("orElse: " + val1);
        
        // orElseGet() - 懒加载默认值
        String val2 = opt2.orElseGet(() -> {
            System.out.println("计算默认值...");
            return "延迟默认值";
        });
        System.out.println("orElseGet: " + val2);
        
        // orElseThrow() - 无值时抛异常
        try {
            String val3 = opt3.orElseThrow(() -> 
                new IllegalStateException("值不存在"));
        } catch (IllegalStateException e) {
            System.out.println("orElseThrow: " + e.getMessage());
        }
        
        // Java 9+ or() - 返回新的Optional
        // Optional<String> opt4 = opt3.or(() -> Optional.of("备选值"));
        
        // === 3. 判断操作 ===
        System.out.println("\n=== 判断操作 ===");
        
        // isPresent() - 是否有值
        boolean hasValue = opt1.isPresent();
        System.out.println("isPresent: " + hasValue);
        
        // ifPresent() - 有值时执行
        opt1.ifPresent(v -> System.out.println("值: " + v));
        
        // Java 9+ ifPresentOrElse()
        // opt3.ifPresentOrElse(
        //     v -> System.out.println("值: " + v),
        //     () -> System.out.println("无值")
        // );
        
        // === 4. 转换操作 ===
        System.out.println("\n=== 转换操作 ===");
        
        // map()
        Optional<Integer> lengthOpt = opt1.map(String::length);
        System.out.println("map: " + lengthOpt);
        
        // flatMap()
        Optional<String> upperOpt = opt1.flatMap(v -> 
            Optional.of(v.toUpperCase()));
        System.out.println("flatMap: " + upperOpt);
        
        // filter()
        Optional<String> filtered = opt1.filter(s -> s.length() > 3);
        System.out.println("filter: " + filtered);
        
        // 链式调用
        Optional<Integer> result = Optional.of("  Hello World  ")
            .map(String::trim)
            .filter(s -> s.length() > 5)
            .map(String::length);
        System.out.println("链式调用: " + result);
        
        // === 5. Stream操作 (Java 9+) ===
        System.out.println("\n=== stream() ===");
        
        // Optional转Stream
        List<String> list1 = opt1.stream()
            .collect(Collectors.toList());
        System.out.println("非空Optional: " + list1);
        
        List<String> list2 = opt3.stream()
            .collect(Collectors.toList());
        System.out.println("空Optional: " + list2);
        
        // 处理可能为null的集合
        List<String> names = null;
        List<String> safeList = Optional.ofNullable(names)
            .orElseGet(Collections::emptyList);
        System.out.println("安全列表: " + safeList);
        
        // === 6. 基本类型Optional ===
        System.out.println("\n=== 基本类型Optional ===");
        
        OptionalInt optInt = OptionalInt.of(42);
        System.out.println("OptionalInt: " + optInt.getAsInt());
        
        OptionalLong optLong = OptionalLong.of(100L);
        System.out.println("OptionalLong: " + optLong.getAsLong());
        
        OptionalDouble optDouble = OptionalDouble.of(3.14);
        System.out.println("OptionalDouble: " + optDouble.getAsDouble());
        
        // === 7. 实战案例 ===
        System.out.println("\n=== 实战案例 ===");
        
        // 案例1:安全的属性访问
        User user = new User("张三", null);
        String city = Optional.ofNullable(user)
            .map(User::getAddress)
            .map(Address::getCity)
            .orElse("未知城市");
        System.out.println("城市: " + city);
        
        // 案例2:条件返回
        String name = getNameById(1);
        String displayName = Optional.ofNullable(name)
            .filter(n -> !n.isEmpty())
            .map(n -> "用户: " + n)
            .orElse("匿名用户");
        System.out.println(displayName);
        
        // 案例3:避免null检查嵌套
        String result2 = Optional.ofNullable(getUserById(1))
            .flatMap(u -> Optional.ofNullable(u.getAddress()))
            .flatMap(a -> Optional.ofNullable(a.getCity()))
            .orElse("默认城市");
        System.out.println("结果: " + result2);
        
        // 案例4:Stream + Optional
        List<User> users = Arrays.asList(
            new User("张三", new Address("北京", "朝阳")),
            new User("李四", null),
            new User("王五", new Address("上海", "浦东"))
        );
        
        List<String> cities = users.stream()
            .map(User::getAddress)
            .filter(Objects::nonNull)
            .map(Address::getCity)
            .collect(Collectors.toList());
        System.out.println("城市列表: " + cities);
        
        // 更优雅的写法
        List<String> cities2 = users.stream()
            .map(u -> Optional.ofNullable(u.getAddress()))
            .flatMap(Optional::stream)
            .map(Address::getCity)
            .collect(Collectors.toList());
        System.out.println("城市列表(优雅): " + cities2);
    }
    
    // 模拟方法
    static String getNameById(int id) {
        return Math.random() > 0.5 ? "用户" + id : null;
    }
    
    static User getUserById(int id) {
        return Math.random() > 0.5 ? new User("用户" + id, null) : null;
    }
}

// 辅助类
class User {
    private String name;
    private Address address;
    
    public User(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    
    public String getName() { return name; }
    public Address getAddress() { return address; }
}

class Address {
    private String city;
    private String street;
    
    public Address(String city, String street) {
        this.city = city;
        this.street = street;
    }
    
    public String getCity() { return city; }
    public String getStreet() { return street; }
}

三、可运行Java代码示例

完整示例1:数据处理管道

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

/**
 * 数据处理管道示例
 */
public class DataPipelineDemo {
    
    // 交易记录
    static class Transaction {
        private int id;
        private String type; // INCOME, EXPENSE
        private String category;
        private double amount;
        private LocalDate date;
        
        public Transaction(int id, String type, String category, 
                          double amount, LocalDate date) {
            this.id = id;
            this.type = type;
            this.category = category;
            this.amount = amount;
            this.date = date;
        }
        
        public int getId() { return id; }
        public String getType() { return type; }
        public String getCategory() { return category; }
        public double getAmount() { return amount; }
        public LocalDate getDate() { return date; }
        
        @Override
        public String toString() {
            return type + ": " + category + " " + amount + "元 (" + date + ")";
        }
    }
    
    public static void main(String[] args) {
        // 模拟交易数据
        List<Transaction> transactions = Arrays.asList(
            new Transaction(1, "INCOME", "工资", 15000, LocalDate.of(2024, 1, 5)),
            new Transaction(2, "EXPENSE", "餐饮", 800, LocalDate.of(2024, 1, 10)),
            new Transaction(3, "EXPENSE", "交通", 300, LocalDate.of(2024, 1, 15)),
            new Transaction(4, "INCOME", "奖金", 5000, LocalDate.of(2024, 1, 20)),
            new Transaction(5, "EXPENSE", "购物", 2000, LocalDate.of(2024, 1, 25)),
            new Transaction(6, "EXPENSE", "餐饮", 600, LocalDate.of(2024, 2, 5)),
            new Transaction(7, "INCOME", "工资", 15000, LocalDate.of(2024, 2, 5)),
            new Transaction(8, "EXPENSE", "娱乐", 1500, LocalDate.of(2024, 2, 10)),
            new Transaction(9, "EXPENSE", "餐饮", 700, LocalDate.of(2024, 2, 15)),
            new Transaction(10, "INCOME", "理财", 2000, LocalDate.of(2024, 2, 20))
        );
        
        // === 1. 计算总收入和总支出 ===
        System.out.println("=== 收支统计 ===");
        
        double totalIncome = transactions.stream()
            .filter(t -> "INCOME".equals(t.getType()))
            .mapToDouble(Transaction::getAmount)
            .sum();
        
        double totalExpense = transactions.stream()
            .filter(t -> "EXPENSE".equals(t.getType()))
            .mapToDouble(Transaction::getAmount)
            .sum();
        
        System.out.println("总收入: " + totalIncome + "元");
        System.out.println("总支出: " + totalExpense + "元");
        System.out.println("结余: " + (totalIncome - totalExpense) + "元");
        
        // === 2. 按类别统计支出 ===
        System.out.println("\n=== 按类别统计支出 ===");
        
        Map<String, Double> expenseByCategory = transactions.stream()
            .filter(t -> "EXPENSE".equals(t.getType()))
            .collect(Collectors.groupingBy(
                Transaction::getCategory,
                Collectors.summingDouble(Transaction::getAmount)
            ));
        
        expenseByCategory.entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .forEach(e -> System.out.println(e.getKey() + ": " + e.getValue() + "元"));
        
        // === 3. 按月份统计 ===
        System.out.println("\n=== 按月份统计 ===");
        
        Map<Month, DoubleSummaryStatistics> monthlyStats = transactions.stream()
            .collect(Collectors.groupingBy(
                t -> t.getDate().getMonth(),
                Collectors.summarizingDouble(Transaction::getAmount)
            ));
        
        monthlyStats.forEach((month, stats) -> {
            System.out.println(month + ": ");
            System.out.println("  交易次数: " + stats.getCount());
            System.out.println("  总金额: " + stats.getSum() + "元");
            System.out.println("  平均: " + String.format("%.2f", stats.getAverage()) + "元");
        });
        
        // === 4. 找出支出最多的类别 ===
        System.out.println("\n=== 支出最多的类别 ===");
        
        Optional<Map.Entry<String, Double>> topCategory = expenseByCategory.entrySet().stream()
            .max(Map.Entry.comparingByValue());
        
        topCategory.ifPresent(e -> 
            System.out.println(e.getKey() + ": " + e.getValue() + "元"));
        
        // === 5. 计算每日平均支出 ===
        System.out.println("\n=== 每日平均支出 ===");
        
        double avgDailyExpense = transactions.stream()
            .filter(t -> "EXPENSE".equals(t.getType()))
            .collect(Collectors.averagingDouble(Transaction::getAmount));
        System.out.println("平均每笔支出: " + String.format("%.2f", avgDailyExpense) + "元");
        
        // === 6. 生成月度报告 ===
        System.out.println("\n=== 月度报告 ===");
        
        Map<Month, Map<String, List<Transaction>>> monthlyReport = transactions.stream()
            .collect(Collectors.groupingBy(
                t -> t.getDate().getMonth(),
                Collectors.groupingBy(Transaction::getType)
            ));
        
        monthlyReport.forEach((month, typeMap) -> {
            System.out.println("\n【" + month + "】");
            typeMap.forEach((type, trans) -> {
                System.out.println("  " + type + ":");
                trans.forEach(t -> 
                    System.out.println("    - " + t.getCategory() + ": " + t.getAmount() + "元"));
            });
        });
        
        // === 7. 检测异常交易(超过平均值2倍)===
        System.out.println("\n=== 异常交易检测 ===");
        
        double avgAmount = transactions.stream()
            .mapToDouble(Transaction::getAmount)
            .average()
            .orElse(0);
        
        List<Transaction> anomalies = transactions.stream()
            .filter(t -> t.getAmount() > avgAmount * 2)
            .collect(Collectors.toList());
        
        System.out.println("平均交易金额: " + String.format("%.2f", avgAmount) + "元");
        System.out.println("异常交易(>平均值2倍):");
        anomalies.forEach(t -> System.out.println("  - " + t));
        
        // === 8. 自定义收集器:生成CSV ===
        System.out.println("\n=== 导出CSV ===");
        
        String csv = transactions.stream()
            .collect(Collectors.collectingAndThen(
                Collectors.mapping(
                    t -> String.join(",",
                        String.valueOf(t.getId()),
                        t.getType(),
                        t.getCategory(),
                        String.valueOf(t.getAmount()),
                        t.getDate().toString()
                    ),
                    Collectors.joining("\n")
                ),
                content -> "id,type,category,amount,date\n" + content
            ));
        System.out.println(csv);
    }
}

// 需要的导入
import java.time.LocalDate;
import java.time.Month;

完整示例2:并行流处理

import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*;

/**
 * 并行流处理示例
 */
public class ParallelStreamDemo {
    
    // 模拟耗时操作
    private static void delay(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    // 模拟数据处理
    private static String processData(int num) {
        delay(100); // 模拟100ms处理时间
        return "Result-" + num;
    }
    
    public static void main(String[] args) {
        List<Integer> numbers = IntStream.rangeClosed(1, 20)
            .boxed()
            .collect(Collectors.toList());
        
        // === 1. 顺序流 vs 并行流性能对比 ===
        System.out.println("=== 顺序流 vs 并行流 ===");
        
        long start1 = System.currentTimeMillis();
        List<String> sequentialResults = numbers.stream()
            .map(ParallelStreamDemo::processData)
            .collect(Collectors.toList());
        long end1 = System.currentTimeMillis();
        System.out.println("顺序流耗时: " + (end1 - start1) + "ms");
        
        long start2 = System.currentTimeMillis();
        List<String> parallelResults = numbers.parallelStream()
            .map(ParallelStreamDemo::processData)
            .collect(Collectors.toList());
        long end2 = System.currentTimeMillis();
        System.out.println("并行流耗时: " + (end2 - start2) + "ms");
        
        // === 2. 并行流中的顺序问题 ===
        System.out.println("\n=== forEach顺序问题 ===");
        
        System.out.println("顺序流:");
        numbers.stream()
            .limit(5)
            .forEach(n -> System.out.print(n + " "));
        System.out.println();
        
        System.out.println("并行流forEach:");
        numbers.parallelStream()
            .limit(5)
            .forEach(n -> System.out.print(n + " "));
        System.out.println();
        
        System.out.println("并行流forEachOrdered:");
        numbers.parallelStream()
            .limit(5)
            .forEachOrdered(n -> System.out.print(n + " "));
        System.out.println();
        
        // === 3. 线程安全的收集 ===
        System.out.println("\n=== 线程安全收集 ===");
        
        // 不安全的方式(可能丢失数据)
        // List<Integer> unsafe = new ArrayList<>();
        // numbers.parallelStream().forEach(unsafe::add); // 不推荐
        
        // 安全方式1:Collectors.toList()
        List<Integer> safe1 = numbers.parallelStream()
            .collect(Collectors.toList());
        System.out.println("toList: " + safe1.size() + "个元素");
        
        // 安全方式2:线程安全容器
        List<Integer> safe2 = numbers.parallelStream()
            .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
        System.out.println("CopyOnWriteArrayList: " + safe2.size() + "个元素");
        
        // 安全方式3:synchronized
        List<Integer> safe3 = Collections.synchronizedList(new ArrayList<>());
        numbers.parallelStream().forEach(safe3::add);
        System.out.println("synchronizedList: " + safe3.size() + "个元素");
        
        // === 4. 并行流的自定义线程池 ===
        System.out.println("\n=== 自定义线程池 ===");
        
        ForkJoinPool customPool = new ForkJoinPool(4);
        
        try {
            List<String> results = customPool.submit(() ->
                numbers.parallelStream()
                    .map(n -> {
                        System.out.println(Thread.currentThread().getName() + 
                            " processing " + n);
                        return "Result-" + n;
                    })
                    .collect(Collectors.toList())
            ).get();
            System.out.println("结果数量: " + results.size());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            customPool.shutdown();
        }
        
        // === 5. 并行流适用场景 ===
        System.out.println("\n=== 并行流适用场景分析 ===");
        
        // 适合:计算密集型、大数据集
        List<Integer> largeList = IntStream.rangeClosed(1, 1000000)
            .boxed()
            .collect(Collectors.toList());
        
        long start3 = System.currentTimeMillis();
        long count1 = largeList.stream()
            .filter(n -> n % 2 == 0)
            .count();
        long end3 = System.currentTimeMillis();
        System.out.println("顺序流过滤100万元素: " + (end3 - start3) + "ms");
        
        long start4 = System.currentTimeMillis();
        long count2 = largeList.parallelStream()
            .filter(n -> n % 2 == 0)
            .count();
        long end4 = System.currentTimeMillis();
        System.out.println("并行流过滤100万元素: " + (end4 - start4) + "ms");
        
        // === 6. 并行流注意事项 ===
        System.out.println("\n=== 并行流注意事项 ===");
        
        // 避免在并行流中使用共享可变状态
        // 错误示例:
        // int[] sum = {0};
        // numbers.parallelStream().forEach(n -> sum[0] += n); // 竞态条件
        
        // 正确做法:使用reduce
        int sum = numbers.parallelStream()
            .reduce(0, Integer::sum);
        System.out.println("求和(reduce): " + sum);
        
        // 使用collect
        int sum2 = numbers.parallelStream()
            .collect(Collectors.summingInt(Integer::intValue));
        System.out.println("求和(collect): " + sum2);
        
        // === 7. 并行流最佳实践 ===
        System.out.println("\n=== 并行流最佳实践 ===");
        
        // 1. 数据量足够大时才使用(通常>10000)
        // 2. 操作是无状态的
        // 3. 避免阻塞操作
        // 4. 注意拆分成本(ArrayList优于LinkedList)
        // 5. 注意装箱拆箱开销(使用原始类型流)
        
        // 原始类型流性能更好
        long start5 = System.currentTimeMillis();
        int sum3 = IntStream.rangeClosed(1, 10000000)
            .parallel()
            .sum();
        long end5 = System.currentTimeMillis();
        System.out.println("IntStream并行求和1000万: " + (end5 - start5) + "ms");
        
        long start6 = System.currentTimeMillis();
        int sum4 = IntStream.rangeClosed(1, 10000000)
            .sum();
        long end6 = System.currentTimeMillis();
        System.out.println("IntStream顺序求和1000万: " + (end6 - start6) + "ms");
    }
}

四、实战应用场景

场景1:集合转换工具

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

/**
 * 集合转换工具类
 */
public class CollectionUtils {
    
    /**
     * List转Map(key冲突时保留第一个)
     */
    public static <K, V> Map<K, V> toMap(List<V> list, 
                                         Function<V, K> keyMapper) {
        return list.stream()
            .collect(Collectors.toMap(
                keyMapper,
                Function.identity(),
                (v1, v2) -> v1
            ));
    }
    
    /**
     * List转Map(自定义key和value)
     */
    public static <T, K, V> Map<K, V> toMap(List<T> list,
                                            Function<T, K> keyMapper,
                                            Function<T, V> valueMapper) {
        return list.stream()
            .collect(Collectors.toMap(
                keyMapper,
                valueMapper,
                (v1, v2) -> v1
            ));
    }
    
    /**
     * List转Map(分组)
     */
    public static <T, K> Map<K, List<T>> groupBy(List<T> list,
                                                  Function<T, K> classifier) {
        return list.stream()
            .collect(Collectors.groupingBy(classifier));
    }
    
    /**
     * List转List(映射)
     */
    public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
        return list.stream()
            .map(mapper)
            .collect(Collectors.toList());
    }
    
    /**
     * 过滤List
     */
    public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
        return list.stream()
            .filter(predicate)
            .collect(Collectors.toList());
    }
    
    /**
     * List去重
     */
    public static <T> List<T> distinct(List<T> list) {
        return list.stream()
            .distinct()
            .collect(Collectors.toList());
    }
    
    /**
     * 按属性去重
     */
    public static <T, R> List<T> distinctBy(List<T> list,
                                            Function<T, R> keyExtractor) {
        Set<R> seen = new HashSet<>();
        return list.stream()
            .filter(t -> seen.add(keyExtractor.apply(t)))
            .collect(Collectors.toList());
    }
    
    /**
     * List排序
     */
    public static <T> List<T> sort(List<T> list,
                                   Comparator<? super T> comparator) {
        return list.stream()
            .sorted(comparator)
            .collect(Collectors.toList());
    }
    
    /**
     * 按属性排序
     */
    public static <T, R extends Comparable<? super R>> List<T> sortBy(
            List<T> list,
            Function<T, R> keyExtractor) {
        return list.stream()
            .sorted(Comparator.comparing(keyExtractor))
            .collect(Collectors.toList());
    }
    
    /**
     * 分页
     */
    public static <T> List<T> page(List<T> list, int pageNum, int pageSize) {
        return list.stream()
            .skip((long) (pageNum - 1) * pageSize)
            .limit(pageSize)
            .collect(Collectors.toList());
    }
    
    /**
     * 连接字符串
     */
    public static <T> String join(List<T> list,
                                  Function<T, String> mapper,
                                  String delimiter) {
        return list.stream()
            .map(mapper)
            .collect(Collectors.joining(delimiter));
    }
    
    /**
     * 扁平化
     */
    public static <T> List<T> flatten(List<List<T>> lists) {
        return lists.stream()
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
    }
    
    /**
     * 查找第一个匹配元素
     */
    public static <T> Optional<T> findFirst(List<T> list, Predicate<T> predicate) {
        return list.stream()
            .filter(predicate)
            .findFirst();
    }
    
    /**
     * 判断是否所有元素匹配
     */
    public static <T> boolean allMatch(List<T> list, Predicate<T> predicate) {
        return list.stream().allMatch(predicate);
    }
    
    /**
     * 判断是否存在匹配元素
     */
    public static <T> boolean anyMatch(List<T> list, Predicate<T> predicate) {
        return list.stream().anyMatch(predicate);
    }
    
    // === 测试 ===
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("张三", 25, "北京"),
            new Person("李四", 30, "上海"),
            new Person("王五", 25, "北京"),
            new Person("赵六", 35, "广州"),
            new Person("钱七", 30, "上海")
        );
        
        // List转Map
        Map<String, Person> nameMap = toMap(people, Person::getName);
        System.out.println("姓名Map: " + nameMap.keySet());
        
        // 分组
        Map<Integer, List<Person>> byAge = groupBy(people, Person::getAge);
        System.out.println("按年龄分组: " + byAge.keySet());
        
        // 映射
        List<String> names = map(people, Person::getName);
        System.out.println("姓名列表: " + names);
        
        // 过滤
        List<Person> beijing = filter(people, p -> "北京".equals(p.getCity()));
        System.out.println("北京: " + map(beijing, Person::getName));
        
        // 按属性去重
        List<Person> distinctByAge = distinctBy(people, Person::getAge);
        System.out.println("按年龄去重: " + map(distinctByAge, Person::getAge));
        
        // 排序
        List<Person> sorted = sortBy(people, Person::getAge);
        System.out.println("按年龄排序: " + map(sorted, Person::getName));
        
        // 分页
        List<Person> page1 = page(people, 1, 2);
        System.out.println("第1页: " + map(page1, Person::getName));
        
        // 连接
        String nameStr = join(people, Person::getName, ", ");
        System.out.println("姓名: " + nameStr);
        
        // 查找
        Optional<Person> first25 = findFirst(people, p -> p.getAge() == 25);
        System.out.println("第一个25岁: " + first25.map(Person::getName).orElse("无"));
        
        // 匹配
        boolean allAdult = allMatch(people, p -> p.getAge() >= 18);
        System.out.println("都是成年人: " + allAdult);
        
        boolean hasBeijing = anyMatch(people, p -> "北京".equals(p.getCity()));
        System.out.println("有北京人: " + hasBeijing);
    }
}

// 辅助类
class Person {
    private String name;
    private int age;
    private String city;
    
    public Person(String name, int age, String city) {
        this.name = name;
        this.age = age;
        this.city = city;
    }
    
    public String getName() { return name; }
    public int getAge() { return age; }
    public String getCity() { return city; }
    
    @Override
    public String toString() {
        return name + "(" + age + ", " + city + ")";
    }
}

场景2:Builder模式增强

import java.util.*;
import java.util.function.*;

/**
 * 使用Lambda增强Builder模式
 */
public class BuilderPatternDemo {
    
    // 传统Builder
    static class User {
        private String name;
        private int age;
        private String email;
        private String phone;
        private List<String> hobbies;
        
        private User(Builder builder) {
            this.name = builder.name;
            this.age = builder.age;
            this.email = builder.email;
            this.phone = builder.phone;
            this.hobbies = builder.hobbies;
        }
        
        // 使用Consumer的方式创建
        public static User of(Consumer<Builder> consumer) {
            Builder builder = new Builder();
            consumer.accept(builder);
            return builder.build();
        }
        
        public static class Builder {
            private String name;
            private int age;
            private String email;
            private String phone;
            private List<String> hobbies = new ArrayList<>();
            
            public Builder name(String name) {
                this.name = name;
                return this;
            }
            
            public Builder age(int age) {
                this.age = age;
                return this;
            }
            
            public Builder email(String email) {
                this.email = email;
                return this;
            }
            
            public Builder phone(String phone) {
                this.phone = phone;
                return this;
            }
            
            public Builder hobby(String hobby) {
                this.hobbies.add(hobby);
                return this;
            }
            
            public User build() {
                return new User(this);
            }
        }
        
        @Override
        public String toString() {
            return "User{name='" + name + "', age=" + age + 
                   ", email='" + email + "', phone='" + phone + 
                   "', hobbies=" + hobbies + "}";
        }
    }
    
    public static void main(String[] args) {
        // 传统Builder方式
        User user1 = new User.Builder()
            .name("张三")
            .age(25)
            .email("zhangsan@example.com")
            .phone("13800138000")
            .hobby("编程")
            .hobby("阅读")
            .build();
        System.out.println("传统Builder: " + user1);
        
        // Lambda方式
        User user2 = User.of(builder -> builder
            .name("李四")
            .age(30)
            .email("lisi@example.com")
            .hobby("游泳")
            .hobby("旅游")
        );
        System.out.println("Lambda方式: " + user2);
        
        // 条件设置
        boolean setEmail = true;
        User user3 = User.of(builder -> {
            builder.name("王五").age(28);
            if (setEmail) {
                builder.email("wangwu@example.com");
            }
        });
        System.out.println("条件设置: " + user3);
    }
}

五、总结与最佳实践

核心要点回顾

概念关键点
Lambda表达式(参数) -> 表达式/语句块,简化匿名内部类
函数式接口只有一个抽象方法的接口,可用@FunctionalInterface标注
方法引用类名::方法名,Lambda的简写形式
Stream API声明式数据处理,支持链式操作和并行处理
Optional避免NullPointerException,提供安全的null处理

四大核心函数式接口

接口方法用途
Consumervoid accept(T t)消费数据
SupplierT get()供给数据
Function<T, R>R apply(T t)转换数据
Predicateboolean test(T t)判断数据

Stream操作分类

类型操作特点
中间操作filter, map, flatMap, distinct, sorted, limit, skip惰性求值,返回新Stream
终止操作collect, reduce, forEach, count, min, max, anyMatch触发计算,产生结果

最佳实践

  1. 优先使用方法引用

    // 推荐
    list.stream().map(String::toUpperCase)
    // 不推荐
    list.stream().map(s -> s.toUpperCase())
    
  2. 合理使用Optional

    // 推荐
    public Optional<User> findById(Long id)
    // 不推荐
    public User findById(Long id)  // 可能返回null
    
  3. 注意Stream的惰性求值

    // 不会执行
    Stream.of(1, 2, 3).filter(n -> {
        System.out.println("filter");  // 不会打印
        return n > 0;
    });
    
    // 会执行
    Stream.of(1, 2, 3).filter(n -> {
        System.out.println("filter");  // 会打印
        return n > 0;
    }).count();
    
  4. 并行流注意事项

    • 数据量大时才考虑(通常>10000)
    • 确保操作无状态
    • 避免共享可变状态
    • 使用线程安全的收集器
  5. 避免装箱拆箱

    // 推荐:使用原始类型流
    int sum = IntStream.range(1, 100).sum();
    
    // 不推荐:会有装箱拆箱开销
    int sum = Stream.of(1, 2, 3).reduce(0, Integer::sum);
    
  6. 链式操作保持简洁

    // 推荐:适当拆分
    List<String> names = people.stream()
        .filter(p -> p.getAge() > 20)
        .collect(Collectors.toList());
    
    List<String> upperNames = names.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());
    
    // 不推荐:过度链式
    people.stream()
        .filter(...)
        .map(...)
        .sorted(...)
        .distinct()
        .limit(...)
        .skip(...)
        .collect(...);
    

常见陷阱

  1. Stream只能消费一次

    Stream<String> stream = Stream.of("A", "B");
    stream.forEach(System.out::println);
    stream.count();  // 报错:stream has already been operated upon
    
  2. 修改数据源

    List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
    // 错误:在流操作中修改数据源
    list.stream().forEach(s -> list.add("C"));  // ConcurrentModificationException
    
  3. 短路操作陷阱

    // findFirst是短路操作,不会处理所有元素
    Optional<Integer> first = Stream.of(1, 2, 3, 4, 5)
        .peek(System.out::println)  // 只打印1
        .filter(n -> n > 3)
        .findFirst();
    
  4. 并行流中的顺序依赖

    // 错误:并行流中不要依赖顺序
    int[] sum = {0};
    IntStream.range(0, 100).parallel()
        .forEach(n -> sum[0] += n);  // 竞态条件
    
    // 正确:使用reduce
    int sum = IntStream.range(0, 100).parallel()
        .reduce(0, Integer::sum);
    

性能优化建议

  1. 选择合适的Stream源

    • ArrayList > LinkedList(分割效率高)
    • 原始类型数组 > 包装类型数组(避免装箱)
  2. 减少中间操作数量

    // 合并多个filter
    .filter(p -> p.getAge() > 18 && p.getAge() < 60)
    // 优于
    .filter(p -> p.getAge() > 18)
    .filter(p -> p.getAge() < 60)
    
  3. 使用合适的收集器

    // 指定初始容量
    .collect(Collectors.toCollection(() -> new ArrayList<>(expectedSize)));
    
  4. 避免不必要的排序

    // 如果不需要排序,不要调用sorted()
    

扩展阅读

  • Java 8函数式编程:《Java 8 in Action》
  • Stream API文档:java.util.stream包
  • Optional最佳实践:避免过度使用Optional作为字段或参数
  • 响应式编程:Reactor、RxJava(Stream的异步版本)