Java Stream API 详解与实战案例
代码语法解析
map.entrySet().stream().filter(entry -> entry.getValue() > 100).map(Map.Entry::getKey).collect(Collectors.toList());
1. map.entrySet().stream()
- **
entrySet()
**: 返回Map中所有键值对的Set视图 - **
stream()
**: 将集合转换为Stream对象,启用流式操作
2. .filter(entry -> entry.getValue() > 100)
- **
filter()
**: 过滤操作,保留满足条件的元素 - Lambda表达式:
entry -> entry.getValue() > 100
- 检查每个键值对的值是否大于100
- 保留值大于100的条目
3. .map(Map.Entry::getKey)
- **
map()
**: 转换操作,将元素映射为另一种形式 - 方法引用:
Map.Entry::getKey
- 将每个键值对转换为它的键(key)
- 相当于
entry -> entry.getKey()
4. .collect(Collectors.toList())
- **
collect()
**: 终止操作,将流转换为集合 - **
Collectors.toList()
**: 收集器,将结果放入List集合
整体流程:
- 获取Map的所有键值对
- 转换为流
- 过滤出值大于100的条目
- 提取这些条目的键
- 收集所有键到一个List中
实际项目案例
案例1:电商平台商品筛选系统
业务需求:筛选出库存量大于100的热门商品ID列表
public class ProductService {// 商品ID -> 库存量private Map<Long, Integer> inventoryMap = new HashMap<>();public List<Long> getPopularProducts() {return inventoryMap.entrySet().stream().filter(entry -> entry.getValue() > 100) // 库存大于100.map(Map.Entry::getKey) // 获取商品ID.collect(Collectors.toList());}// 添加商品库存public void addProductInventory(Long productId, Integer stock) {inventoryMap.put(productId, stock);}
}
使用场景:
public class Main {public static void main(String[] args) {ProductService service = new ProductService();// 添加商品库存service.addProductInventory(1001L, 150);service.addProductInventory(1002L, 80);service.addProductInventory(1003L, 200);service.addProductInventory(1004L, 300);// 获取热门商品IDList<Long> popularProducts = service.getPopularProducts();System.out.println("库存充足的热门商品: " + popularProducts);// 输出: [1001, 1003, 1004]}
}
案例2:用户活跃度分析系统
业务需求:找出最近7天登录次数超过100次的活跃用户
public class UserActivityService {// 用户ID -> 登录次数private Map<String, Integer> loginCountMap = new HashMap<>();public List<String> getActiveUsers() {return loginCountMap.entrySet().stream().filter(entry -> entry.getValue() > 100) // 登录超过100次.map(Map.Entry::getKey) // 获取用户ID.collect(Collectors.toList());}// 记录用户登录public void recordUserLogin(String userId) {loginCountMap.put(userId, loginCountMap.getOrDefault(userId, 0) + 1);}
}
使用场景:
public class Main {public static void main(String[] args) {UserActivityService service = new UserActivityService();// 模拟用户登录service.recordUserLogin("user001");service.recordUserLogin("user002");// ... 多次登录记录// 设置测试数据service.loginCountMap.put("user001", 120);service.loginCountMap.put("user002", 85);service.loginCountMap.put("user003", 150);// 获取活跃用户List<String> activeUsers = service.getActiveUsers();System.out.println("活跃用户: " + activeUsers);// 输出: [user001, user003]}
}
案例3:服务器监控告警系统
业务需求:筛选出CPU使用率超过100%的服务器
public class ServerMonitor {// 服务器ID -> CPU使用率(%)private Map<String, Double> cpuUsageMap = new HashMap<>();public List<String> getOverloadedServers() {return cpuUsageMap.entrySet().stream().filter(entry -> entry.getValue() > 100.0) // CPU使用率超过100%.map(Map.Entry::getKey) // 获取服务器ID.collect(Collectors.toList());}// 更新服务器状态public void updateServerStatus(String serverId, double cpuUsage) {cpuUsageMap.put(serverId, cpuUsage);}
}
使用场景:
public class Main {public static void main(String[] args) {ServerMonitor monitor = new ServerMonitor();// 更新服务器状态monitor.updateServerStatus("server-01", 85.2);monitor.updateServerStatus("server-02", 110.5);monitor.updateServerStatus("server-03", 95.7);monitor.updateServerStatus("server-04", 125.0);// 获取过载服务器列表List<String> overloadedServers = monitor.getOverloadedServers();System.out.println("需要关注的服务器: " + overloadedServers);// 输出: [server-02, server-04]// 触发告警if (!overloadedServers.isEmpty()) {sendAlert(overloadedServers);}}private static void sendAlert(List<String> servers) {System.out.println("告警: 以下服务器CPU过载: " + servers);// 实际项目中发送邮件或短信告警}
}
高级应用技巧
1. 多条件过滤
// 筛选库存大于100且价格低于50的商品
List<Long> products = productMap.entrySet().stream().filter(entry -> entry.getValue().getStock() > 100).filter(entry -> entry.getValue().getPrice() < 50).map(Map.Entry::getKey).collect(Collectors.toList());
2. 并行处理提升性能
List<String> activeUsers = loginCountMap.entrySet().parallelStream().filter(entry -> entry.getValue() > 100).map(Map.Entry::getKey).collect(Collectors.toList());
3. 自定义收集器
// 收集到Set去重
Set<String> uniqueServers = cpuUsageMap.entrySet().stream().filter(entry -> entry.getValue() > 100).map(Map.Entry::getKey).collect(Collectors.toSet());// 收集到自定义集合
TreeSet<String> sortedUsers = loginCountMap.entrySet().stream().filter(entry -> entry.getValue() > 100).map(Map.Entry::getKey).collect(Collectors.toCollection(TreeSet::new));
4. 结合Optional处理空值
List<String> activeUsers = Optional.ofNullable(loginCountMap).map(Map::entrySet).orElse(Collections.emptySet()).stream().filter(entry -> entry.getValue() > 100).map(Map.Entry::getKey).collect(Collectors.toList());
性能优化建议
避免在流中执行耗时操作:
// 不推荐 - 在filter中执行数据库查询 .filter(entry -> userDao.isActive(entry.getKey()))// 推荐 - 预先加载数据 Set<String> activeUserIds = userDao.getActiveUserIds(); .filter(entry -> activeUserIds.contains(entry.getKey()))
合理使用并行流:
- 数据量 > 10000时考虑使用
- 避免在共享资源上使用
- 注意线程安全问题
减少中间操作:
// 优化前 .map(Map.Entry::getValue) .filter(value -> value > 100) .map(value -> value * 1.1)// 优化后 .filter(entry -> entry.getValue() > 100) .map(entry -> entry.getValue() * 1.1)
使用基本类型特化流:
// 优化前 - 有装箱开销 map.values().stream().filter(v -> v > 100).count()// 优化后 map.values().stream().mapToInt(Integer::intValue).filter(v -> v > 100).count()
总结
Java Stream API 提供了一种声明式、函数式的数据处理方式,特别适合对集合进行过滤、映射和聚合操作。本文解析的代码模式:
map.entrySet().stream().filter(condition).map(transformation).collect(result)
在实际项目中具有广泛应用价值:
- 电商系统:筛选热门商品、高库存商品
- 用户分析:识别活跃用户、VIP用户
- 监控系统:检测异常服务器、过载服务
- 金融系统:找出高风险交易、大额转账
- 物联网应用:过滤异常传感器数据
使用Stream API的优势:
- 代码简洁:链式调用取代多层嵌套循环
- 可读性强:声明式表达业务意图
- 易于并行:parallelStream()简单启用并行处理
- 函数式风格:无副作用,更易维护
掌握Stream API的使用技巧,能够显著提升Java开发效率和代码质量,是现代Java开发者必备的核心技能之一。