一、Stream 特点:

  • 不存储数据,只是数据源的一个视图

  • 函数式编程,对流的操作产生一个新流

  • 延迟执行,中间操作都是惰性的

  • 不可重复使用,消费后会失效

二、 创建方式

// 1. 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();
Stream<String> parallelStream = list.parallelStream(); // 并行流

// 2. 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);
Stream<String> stream3 = Stream.of("a", "b", "c");

// 3. 使用 Stream.builder()
Stream<String> stream4 = Stream.<String>builder()
    .add("a")
    .add("b")
    .add("c")
    .build();

// 4. 生成无限流
Stream<Integer> generate = Stream.generate(() -> 1).limit(10);
Stream<Integer> iterate = Stream.iterate(0, n -> n + 2).limit(10);

// 5. 基本类型特化流
IntStream intStream = IntStream.range(1, 10);      // 1-9
IntStream intStream2 = IntStream.rangeClosed(1, 10); // 1-10

三、使用

1. 筛选与切片

// filter - 筛选条件 过滤元素
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> even = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList()); // [2, 4, 6]

// distinct - 去重
List<Integer> withDuplicates = Arrays.asList(1, 2, 2, 3, 3, 4);
List<Integer> distinct = withDuplicates.stream()
    .distinct()
    .collect(Collectors.toList()); // [1, 2, 3, 4]

// limit - 限制数量
List<Integer> firstThree = numbers.stream()
    .limit(3)
    .collect(Collectors.toList()); // [1, 2, 3]

// skip - 跳过前几个元素
List<Integer> afterSkip = numbers.stream()
    .skip(2)
    .collect(Collectors.toList()); // [3, 4, 5, 6]

2. 映射

// map - 元素转换
List<String> words = Arrays.asList("111", "222");
List<Integer> lengths = words.stream()
    .map(Integer::parseInt)
    .collect(Collectors.toList()); // [111, 222]

// 对象属性提取
List<User> users = getUsers();
List<String> names = users.stream()
    .map(User::getName)
    .collect(Collectors.toList());

// flatMap - 扁平化映射
List<List<Integer>> listOfLists = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
List<Integer> flatList = listOfLists.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList()); // [1, 2, 3, 4, 5, 6]

// 拆分字符串
List<String> sentences = Arrays.asList("Hello World", "Java Stream");
List<String> words2 = sentences.stream()
    .flatMap(s -> Arrays.stream(s.split(" ")))
    .collect(Collectors.toList()); // ["Hello", "World", "Java", "Stream"]

3. 排序

// sorted - 自然排序
List<Integer> unsorted = Arrays.asList(3, 1, 4, 1, 5);
List<Integer> sorted = unsorted.stream()
    .sorted()
    .collect(Collectors.toList()); // [1, 1, 3, 4, 5]

// 自定义排序
List<User> sortedUsers = users.stream()
    .sorted(Comparator.comparing(User::getAge))
    .collect(Collectors.toList());

// 多级排序
List<User> sortedUsers2 = users.stream()
    .sorted(Comparator.comparing(User::getAge)
        .thenComparing(User::getName))
    .collect(Collectors.toList());

// 反向排序
List<Integer> reverseSorted = unsorted.stream()
    .sorted(Comparator.reverseOrder())
    .collect(Collectors.toList()); // [5, 4, 3, 1, 1]

4. 调试

// peek - 查看中间结果
List<Integer> result = Stream.of(1, 2, 3, 4)
    .peek(x -> System.out.println("原始值: " + x))
    .map(x -> x * 2)
    .peek(x -> System.out.println("映射后: " + x))
    .filter(x -> x > 5)
    .peek(x -> System.out.println("过滤后: " + x))
    .collect(Collectors.toList());

5. 匹配与查找

// allMatch - 全部匹配
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);

// anyMatch - 任一匹配
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);

// noneMatch - 无匹配
boolean noNegative = numbers.stream().noneMatch(n -> n < 0);

// findFirst - 返回第一个
Optional<Integer> first = numbers.stream()
    .filter(n -> n > 3)
    .findFirst();

// findAny - 返回任意一个(并行流中效率高)
Optional<Integer> any = numbers.parallelStream()
    .filter(n -> n > 3)
    .findAny();

6. 归约

// count - 计数
long count = numbers.stream().count();
long evenCount = numbers.stream().filter(n -> n % 2 == 0).count();

// max/min - 最大/最小值
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
Optional<Integer> min = numbers.stream().min(Integer::compareTo);

// reduce - 累积计算
// 求和
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
// 带初始值
Integer sumWithInit = numbers.stream().reduce(0, (a, b) -> a + b);
// 方法引用
Integer sumWithMethod = numbers.stream().reduce(0, Integer::sum);

// 求最大值
Optional<Integer> max2 = numbers.stream().reduce(Integer::max);

// 字符串拼接
List<String> strs = Arrays.asList("a", "b", "c");
String concat = strs.stream().reduce("", (a, b) -> a + b); // "abc"

7. 收集

// collect - 收集到集合
// 转 List
List<String> nameList = users.stream()
    .map(User::getName)
    .collect(Collectors.toList());

// 转 Set(自动去重)
Set<String> nameSet = users.stream()
    .map(User::getName)
    .collect(Collectors.toSet());

// 转特定集合类型
ArrayList<String> arrayList = users.stream()
    .map(User::getName)
    .collect(Collectors.toCollection(ArrayList::new));

TreeSet<String> treeSet = users.stream()
    .map(User::getName)
    .collect(Collectors.toCollection(TreeSet::new));

// 转 Map
Map<Integer, String> userMap = users.stream()
    .collect(Collectors.toMap(
        User::getId,      // key mapper
        User::getName,    // value mapper
        (v1, v2) -> v1    // 冲突解决
    ));

// 分组
Map<Integer, List<User>> groupByAge = users.stream()
    .collect(Collectors.groupingBy(User::getAge));

// 多级分组
Map<Integer, Map<String, List<User>>> multiGroup = users.stream()
    .collect(Collectors.groupingBy(User::getAge, 
             Collectors.groupingBy(User::getGender)));

// 分区(true/false两组)
Map<Boolean, List<Integer>> partition = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n > 3));

// 连接字符串
String joined = words.stream()
    .collect(Collectors.joining(", ", "[", "]"));
// 输出: [hello, world]

// 汇总统计
IntSummaryStatistics stats = numbers.stream()
    .collect(Collectors.summarizingInt(Integer::intValue));
System.out.println(stats.getSum());
System.out.println(stats.getAverage());
System.out.println(stats.getMax());
System.out.println(stats.getMin());
System.out.println(stats.getCount());

四、数值流特化

// IntStream, LongStream, DoubleStream 避免装箱开销
int[] intArray = {1, 2, 3, 4, 5};

// 范围操作
IntStream.range(1, 10).forEach(System.out::print);    // 123456789
IntStream.rangeClosed(1, 10).forEach(System.out::print); // 12345678910

// 数值计算
int sum = IntStream.of(1, 2, 3, 4, 5).sum();
OptionalDouble avg = IntStream.of(1, 2, 3, 4, 5).average();
int max = IntStream.of(1, 2, 3, 4, 5).max().getAsInt();

// 对象流转数值流
List<User> users = getUsers();
int totalAge = users.stream()
    .mapToInt(User::getAge)
    .sum();

double avgAge = users.stream()
    .mapToInt(User::getAge)
    .average()
    .orElse(0);

// 数值流转回对象流
Stream<String> boxedStream = IntStream.range(1, 5)
    .boxed()
    .map(Object::toString);

五、并行流

// 创建并行流
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
list.parallelStream().forEach(System.out::println);

// 将串行流转并行
list.stream().parallel().forEach(System.out::println);

// 并行流归约(线程安全)
int sum = list.parallelStream()
    .reduce(0, Integer::sum); // 正确

// 错误用法 - 非线程安全的集合
List<Integer> wrongResult = new ArrayList<>();
list.parallelStream()
    .forEach(wrongResult::add); // 可能丢失数据或抛异常

// 正确用法
List<Integer> rightResult = list.parallelStream()
    .collect(Collectors.toList());

// 控制并行度
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "4");

六、案例

案例1:复杂对象处理

@Data
@AllArgsConstructor
class Order {
    private Long id;
    private Double amount;
    private LocalDateTime createTime;
    private List<OrderItem> items;
}

@Data
@AllArgsConstructor
class OrderItem {
    private String productName;
    private Integer quantity;
    private Double price;
}

// 统计每个用户的总订单金额
Map<User, Double> userTotalAmount = orders.stream()
    .collect(Collectors.groupingBy(
        Order::getUser,
        Collectors.summingDouble(Order::getAmount)
    ));

// 获取最近7天的订单数量
long recentOrders = orders.stream()
    .filter(order -> order.getCreateTime()
        .isAfter(LocalDateTime.now().minusDays(7)))
    .count();

// 计算订单总金额
double totalAmount = orders.stream()
    .mapToDouble(Order::getAmount)
    .sum();

// 获取最贵的订单
Optional<Order> maxOrder = orders.stream()
    .max(Comparator.comparing(Order::getAmount));

// 订单金额分布(区间)
Map<String, List<Order>> amountDistribution = orders.stream()
    .collect(Collectors.groupingBy(order -> {
        if (order.getAmount() < 100) return "小额";
        if (order.getAmount() < 1000) return "中额";
        return "大额";
    }));

案例2:文件处理

// 读取文件并统计单词频率
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    Map<String, Long> wordCount = lines
        .flatMap(line -> Arrays.stream(line.split("\\W+")))
        .filter(word -> word.length() > 0)
        .map(String::toLowerCase)
        .collect(Collectors.groupingBy(
            Function.identity(), 
            Collectors.counting()
        ));
    
    // 获取前10个高频词
    wordCount.entrySet().stream()
        .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
        .limit(10)
        .forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
}

七、踩坑记录

1. Stream 不可重用

Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 抛异常: stream has already been operated upon

2. 无限流必须限制

Stream.generate(Math::random)
    .limit(10)  // 必须添加限制
    .forEach(System.out::println);

3. Lambda 外部变量必须是 final 或 effectively final

String prefix = "User: ";
Stream.of("Alice", "Bob")
    .map(name -> prefix + name)  // prefix 是 effectively final
    .forEach(System.out::println);

4. 短路操作优化

// findFirst, findAny, limit, anyMatch 都是短路操作
// 应该尽早使用
list.stream()
    .filter(this::expensiveOperation)  // 昂贵的操作
    .findFirst()  // 只执行到第一个匹配
    .ifPresent(System.out::println);

持续更新中。。。。。。

更多推荐