尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

JDK8 Stream API详解:从概念到实战应用

JDK8 Stream API详解:从概念到实战应用 1. JDK8 Stream核心概念解析Stream是JDK8引入的全新API它允许我们以声明式的方式处理数据集合。与传统的集合操作不同Stream操作更像是数据库查询——你只需要告诉它你想要什么而不需要关心具体如何实现。Stream的核心特点可以概括为流水线操作多个操作可以连接起来形成一个流水线内部迭代迭代操作由Stream API在背后完成延迟执行只有调用终端操作时才会真正执行并行能力只需调用parallel()就能实现并行处理// 典型Stream使用示例 ListString names Arrays.asList(John, Alice, Bob, Cathy); long count names.stream() .filter(name - name.length() 3) .count();2. Stream操作类型详解2.1 中间操作(Intermediate Operations)中间操作会返回一个新的Stream允许我们进行链式调用。常见中间操作包括filter(Predicate predicate)过滤不符合条件的元素示例.filter(s - s.startsWith(A))map(FunctionT,R mapper)将元素转换为其他形式示例.map(String::toUpperCase)flatMap(FunctionT,Stream mapper)将每个元素转换为流然后把所有流连接起来示例.flatMap(line - Arrays.stream(line.split( )))distinct()去重依赖equals方法示例.distinct()sorted() / sorted(Comparator comparator)排序自然排序或自定义排序示例.sorted(Comparator.reverseOrder())peek(Consumer action)查看流经的元素主要用于调试示例.peek(System.out::println)2.2 终端操作(Terminal Operations)终端操作会消耗流产生一个非流的结果forEach(Consumer action)对每个元素执行操作示例.forEach(System.out::println)collect(CollectorT,A,R collector)将流转换为集合或其他形式示例.collect(Collectors.toList())reduce(...)将流元素组合起来示例.reduce(0, Integer::sum)count()统计元素数量示例.count()anyMatch/allMatch/noneMatch(Predicate predicate)检查是否匹配任何/所有/没有元素示例.anyMatch(s - s.contains(a))3. Stream高级特性与应用3.1 并行流处理Stream可以轻松实现并行处理ListString names Arrays.asList(John, Alice, Bob, Cathy); long count names.parallelStream() // 只需改为parallelStream .filter(name - name.length() 3) .count();注意并行流并不总是更快需要考虑数据量、操作复杂度和线程开销等因素。3.2 原始类型特化流为避免装箱/拆箱开销Stream提供了原始类型特化流IntStreamLongStreamDoubleStreamIntStream.range(1, 100) // 不包含100 .filter(n - n % 2 0) .sum();3.3 流构建方式除了从集合创建流还可以通过多种方式构建流值创建StreamString stream Stream.of(A, B, C);数组创建String[] array {A, B, C}; StreamString stream Arrays.stream(array);文件创建StreamString lines Files.lines(Paths.get(data.txt));函数生成// 无限流 Stream.iterate(0, n - n 2) .limit(10) .forEach(System.out::println); // 随机数流 Stream.generate(Math::random) .limit(5) .forEach(System.out::println);4. 实用Collector操作Collectors类提供了丰富的收集器实现4.1 转换为集合ListString list stream.collect(Collectors.toList()); SetString set stream.collect(Collectors.toSet());4.2 连接字符串String joined stream.collect(Collectors.joining(, ));4.3 分组和分区// 分组 MapInteger, ListPerson byAge persons.stream() .collect(Collectors.groupingBy(Person::getAge)); // 多级分组 MapInteger, MapString, ListPerson byAgeAndCity persons.stream() .collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getCity))); // 分区 MapBoolean, ListPerson partitioned persons.stream() .collect(Collectors.partitioningBy(p - p.getAge() 18));4.4 统计汇总IntSummaryStatistics stats persons.stream() .collect(Collectors.summarizingInt(Person::getAge)); // 包含count, sum, min, average, max5. 性能优化与最佳实践5.1 流操作顺序优化流的操作顺序会影响性能// 较差的方式 - 先映射再过滤 stream.map(expensiveOperation) .filter(x - x 10) .count(); // 更好的方式 - 先过滤再映射 stream.filter(x - x 10) .map(expensiveOperation) .count();5.2 避免状态操作无状态操作(filter, map等)比有状态操作(sorted, distinct等)性能更好应尽量减少有状态操作的使用。5.3 短路操作利用anyMatch、findFirst等短路操作可以在找到结果后立即终止处理提高效率。5.4 重用与关闭流不能被重复使用尝试重用会抛出IllegalStateException。基于IO的流(如Files.lines)需要手动关闭或使用try-with-resourcestry (StreamString lines Files.lines(path)) { lines.forEach(System.out::println); }6. 常见问题与解决方案6.1 流只能被消费一次StreamString stream Stream.of(A, B, C); stream.forEach(System.out::println); stream.forEach(System.out::println); // 抛出IllegalStateException解决方案每次需要时重新创建流。6.2 并行流线程安全问题ListString results new ArrayList(); stream.parallel().forEach(s - results.add(s)); // 线程不安全解决方案使用线程安全的收集器ListString results stream.parallel() .collect(Collectors.toList());6.3 无限流处理Stream.iterate(0, i - i 1).forEach(System.out::println); // 无限循环解决方案总是配合limit()使用Stream.iterate(0, i - i 1) .limit(100) .forEach(System.out::println);6.4 原始类型与包装类型转换IntStream intStream Stream.of(1, 2, 3).mapToInt(x - x); StreamInteger boxed intStream.boxed();7. 实际应用案例7.1 文件处理统计文件中各单词出现频率MapString, Long wordCount Files.lines(Paths.get(data.txt)) .flatMap(line - Arrays.stream(line.split(\\W))) .filter(word - !word.isEmpty()) .collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));7.2 数据库查询模拟模拟分页查询ListPerson page persons.stream() .sorted(Comparator.comparing(Person::getName)) .skip((pageNum - 1) * pageSize) .limit(pageSize) .collect(Collectors.toList());7.3 复杂数据转换将人员列表转换为树形结构MapDepartment, MapTeam, ListEmployee orgTree employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getTeam)));
返回列表