如何做后台网站增删改,网站推广服务chuseo,wordpress sensica,温州企业网站seoJava 8 Stream 介绍
1. 什么是Stream#xff1f;
Stream#xff08;流#xff09;是Java 8引入的全新概念#xff0c;它是一个支持串行和并行聚合操作的元素序列。Stream API提供了一种声明式的方式来处理数据集合#xff0c;可以让我们以一种类似SQL查询的方式处理数据…Java 8 Stream 介绍
1. 什么是Stream
Stream流是Java 8引入的全新概念它是一个支持串行和并行聚合操作的元素序列。Stream API提供了一种声明式的方式来处理数据集合可以让我们以一种类似SQL查询的方式处理数据。
Stream的特点
声明式处理通过声明要做什么而不是如何做链式操作支持多个操作的链式调用惰性计算中间操作不会立即执行可并行易于转换为并行操作一次性使用Stream只能被消费一次
2. Stream的基本用法
1. 创建Stream
// 1. 从Collection创建
ListString list Arrays.asList(a, b, c);
StreamString stream1 list.stream();// 2. 从数组创建
String[] array {a, b, c};
StreamString stream2 Arrays.stream(array);// 3. 使用Stream.of()
StreamString stream3 Stream.of(a, b, c);// 4. 创建数值流
IntStream intStream IntStream.range(1, 5); // 1,2,3,4
DoubleStream doubleStream DoubleStream.of(1.1, 2.2, 3.3);// 5. 创建无限流
StreamInteger infiniteStream Stream.iterate(0, n - n 2); // 偶数流
StreamDouble randomStream Stream.generate(Math::random); // 随机数流2. Stream操作的类型
Stream API的操作可以分为两类
2.1 中间操作Intermediate Operations
返回新的Stream是惰性的lazy不会立即执行
// 常见的中间操作
StreamString stream list.stream().filter(s - s.length() 3) // 过滤.map(String::toUpperCase) // 转换.distinct() // 去重.sorted() // 排序.limit(5); // 限制数量2.2 终端操作Terminal Operations
产生结果会触发实际计算执行后Stream不能再被使用
// 常见的终端操作
long count stream.count(); // 计数
ListString result stream.collect(Collectors.toList()); // 收集到List
String joined stream.collect(Collectors.joining(, )); // 连接字符串3. Stream的常用操作示例
1. 过滤和映射
ListString names Arrays.asList(John, Jane, Adam, Tom);// 过滤以J开头的名字并转换为大写
ListString filteredNames names.stream().filter(name - name.startsWith(J)).map(String::toUpperCase).collect(Collectors.toList());
// 结果: [JOHN, JANE]// map一对一映射
ListString words Arrays.asList(hello, world);
ListInteger wordLengths words.stream().map(String::length).collect(Collectors.toList()); // [5, 5]// flatMap一对多映射
ListListInteger nestedNumbers Arrays.asList(Arrays.asList(1, 2, 3),Arrays.asList(4, 5, 6)
);
ListInteger flattenedNumbers nestedNumbers.stream().flatMap(Collection::stream).collect(Collectors.toList()); // [1, 2, 3, 4, 5, 6]2. 排序和限制
/ 自然排序
ListInteger sorted numbers.stream().sorted().collect(Collectors.toList());// 自定义排序
ListString names Arrays.asList(John, Jane, Adam);
ListString sortedByLength names.stream().sorted(Comparator.comparing(String::length)).collect(Collectors.toList());// 反向排序
ListInteger reverseSorted numbers.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());// 获取前3个最大的数字
ListInteger numbers Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5);ListInteger top3 numbers.stream().sorted(Comparator.reverseOrder()).distinct().limit(3).collect(Collectors.toList());
// 结果: [9, 6, 5]3. 统计和汇总
ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 基本统计
IntSummaryStatistics stats numbers.stream().mapToInt(Integer::intValue).summaryStatistics();System.out.println(Average: stats.getAverage()); // 3.0
System.out.println(Sum: stats.getSum()); // 15
System.out.println(Max: stats.getMax()); // 5
System.out.println(Min: stats.getMin()); // 14. 分组和分区
ListPerson people Arrays.asList(new Person(John, 25),new Person(Jane, 30),new Person(Adam, 25)
);// 按年龄分组
MapInteger, ListPerson byAge people.stream().collect(Collectors.groupingBy(Person::getAge));// 按年龄是否大于27分区
MapBoolean, ListPerson partitioned people.stream().collect(Collectors.partitioningBy(p - p.getAge() 27));5. 收集结果
// 收集为List
ListInteger list numbers.stream().collect(Collectors.toList());// 收集为Set
SetInteger set numbers.stream().collect(Collectors.toSet());// 收集为Map
MapString, Integer map names.stream().collect(Collectors.toMap(Function.identity(), // 键映射函数String::length // 值映射函数));// 连接字符串
String joined names.stream().collect(Collectors.joining(, ));3.2 规约操作
// reduce求和
int sum numbers.stream().reduce(0, Integer::sum);// reduce求最大值
OptionalInteger max numbers.stream().reduce(Integer::max);// reduce字符串连接
String concatenated words.stream().reduce(, String::concat);3.4 匹配操作
// anyMatch是否存在匹配元素
boolean hasEven numbers.stream().anyMatch(n - n % 2 0);// allMatch是否所有元素都匹配
boolean allEven numbers.stream().allMatch(n - n % 2 0);// noneMatch是否没有匹配元素
boolean noneNegative numbers.stream().noneMatch(n - n 0);4. 并行流操作
4.1 创建并行流
// 从集合创建并行流
ListInteger parallelResult numbers.parallelStream().map(n - n * 2).collect(Collectors.toList());// 将顺序流转换为并行流
ListInteger parallelResult2 numbers.stream().parallel().map(n - n * 2).collect(Collectors.toList());4.2 并行流注意事项
// 使用forEachOrdered保证顺序
numbers.parallelStream().forEachOrdered(System.out::println);// 使用线程安全的收集器
ListInteger syncList numbers.parallelStream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));## Stream使用的注意事项1. **Stream不存储数据**- Stream不是数据结构- Stream只是用于计算的抽象2. **Stream操作是惰性的**- 中间操作不会立即执行- 只有遇到终端操作时才会执行3. **Stream不能重复使用**
java
StreamString stream list.stream();
stream.forEach(System.out::println);
// 下面的代码会抛出异常
stream.forEach(System.out::println); // IllegalStateException注意空指针
// 推荐使用Optional避免空指针
OptionalString first stream.filter(s - s.length() 3).findFirst();合理使用并行流
// 数据量大时使用并行流可提高性能
ListInteger result numbers.parallelStream().filter(n - n 100).collect(Collectors.toList());5. 实际应用示例
5.1 数据过滤和转换
class Person {String name;int age;String city;// 构造函数和getter/setter省略
}ListPerson people // 假设这里有一个Person列表// 获取所有成年人的姓名按字母排序
ListString adultNames people.stream().filter(p - p.getAge() 18).map(Person::getName).sorted().collect(Collectors.toList());// 按城市对人进行分组
MapString, ListPerson peopleByCity people.stream().collect(Collectors.groupingBy(Person::getCity));5.2 复杂数据处理
// 计算每个城市的平均年龄
MapString, Double avgAgeByCity people.stream().collect(Collectors.groupingBy(Person::getCity,Collectors.averagingInt(Person::getAge)));// 找出每个城市年龄最大的人
MapString, OptionalPerson oldestByCity people.stream().collect(Collectors.groupingBy(Person::getCity,Collectors.maxBy(Comparator.comparing(Person::getAge))));6. 最佳实践 使用Stream的时机 当需要对集合进行复杂操作时当操作可以被链式调用表示时当需要并行处理数据时 性能考虑 避免过度使用Stream注意中间操作的顺序例如先filter后map通常更高效大数据量时考虑使用并行流 代码可读性 适当换行以提高可读性使用有意义的变量名复杂操作添加适当的注释 调试技巧 使用peek()方法调试中间结果合理拆分复杂的Stream操作链使用适当的日志记录
7. 常见问题和解决方案
无限流的处理
// 错误示例
Stream.iterate(0, n - n 1); // 无限流// 正确示例
Stream.iterate(0, n - n 1).limit(10); // 限制元素数量并行流的线程安全
// 错误示例
ListString result new ArrayList();
stream.parallel().forEach(result::add); // 线程不安全// 正确示例
ListString result stream.parallel().collect(Collectors.toList()); // 使用线程安全的收集器Stream重复使用
// 错误示例
StreamString stream list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 抛出异常// 正确示例
list.stream().forEach(System.out::println);
list.stream().forEach(System.out::println); // 每次创建新的Stream8. Stream的优势 代码简洁 使用Stream可以用更少的代码完成复杂的数据处理 提高可读性 声明式的处理方式更容易理解代码意图 支持并行 轻松实现并行处理提高性能 延迟执行 惰性计算提高了程序效率
9. 实际应用场景
数据过滤和转换
// 过滤和转换用户数据
ListUserDTO userDTOs users.stream().filter(user - user.isActive()).map(user - convertToDTO(user)).collect(Collectors.toList());数据统计分析
// 计算订单总金额
double totalAmount orders.stream().mapToDouble(Order::getAmount).sum();复杂数据处理
// 按部门统计员工平均工资
MapString, Double avgSalaryByDept employees.stream().collect(Collectors.groupingBy(Employee::getDepartment,Collectors.averagingDouble(Employee::getSalary)));