在最近的練手項目中,對于stream流的操作愈加頻繁,我也越來越感覺stream流在處理數據是的干凈利落,因此寫博客用來記錄最近常用的方法以便于未來的復習。
map() 方法
map()是一個中間操作(intermediate operation),用于將流中的每個元素按照給定的函數進行轉換。
常見用法示例:
// 在RoleController中,將Role對象轉換為RoleDTO對象
List<RoleDTO> dtos = list.stream().map(Role::toDTO).collect(Collectors.toList());// 在MenuController中,將Menu對象轉換為MenuOptionVO對象
List<MenuOptionVO> menus = list.stream().map(MenuOptionVO::new).collect(Collectors.toList());// 在CouponServiceImpl中,將bizId轉換為CouponScope對象
List<CouponScope> newScopeList = newScopes.stream().map(bizId -> new CouponScope().setBizId(bizId).setCouponId(couponId)).collect(Collectors.toList());
collect() 方法
collect()是一個終端操作(terminal operation),用于將流中的元素收集到集合或其他數據結構中。
常見的收集器(Collectors)用法:
1. Collectors.toList() - 收集到List中
// 收集為List
List<RoleDTO> dtoList = list.stream().map(Role::toDTO).collect(Collectors.toList());
2. Collectors.toSet() - 收集到Set中
// 在PointsBoardServiceImpl中收集用戶ID為Set
Set<Long> userIds = list.stream().map(PointsBoard::getUserId).collect(Collectors.toSet());
3. Collectors.toMap() - 收集到Map中
// 在LearningLessonServiceImpl中,將課程信息收集為Map
Map<Long, CourseSimpleInfoDTO> cMap = cInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));// 在PointsBoardServiceImpl中,將用戶信息收集為Map
Map<Long, String> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));// 在CartServiceImpl中,將課程信息收集為Map
Map<Long, CourseSimpleInfoDTO> courseMap = courseSimpleInfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
4. Collectors.groupingBy() - 按條件分組
// 在CouponServiceImpl中,按優惠券ID分組并統計數量
Map<Long, Long> unUseMap = list.stream().filter(userCoupon -> userCoupon.getStatus() == UserCouponStatus.UNUSED).collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));// 在CourseCatalogueServiceImpl中,按媒資ID分組并統計引用次數
Map<Long, Long> mediaAndCount = courseCatalogues.stream().collect(Collectors.groupingBy(CourseCatalogue::getMediaId, Collectors.counting()));
實際應用示例
讓我們看一個更復雜的例子,來自CouponServiceImpl:
// 統計當前用戶針對每一個卷已領取且未使用的數量
//filter過濾得到未使用的
Map<Long, Long> unUseMap = list.stream().filter(userCoupon -> userCoupon.getStatus() == UserCouponStatus.UNUSED).collect(Collectors.groupingBy(UserCoupon::getCouponId, Collectors.counting()));
這個例子展示了:
使用filter()進行篩選(只保留未使用的優惠券)
使用collect()結合Collectors.groupingBy()進行分組
使用Collectors.counting()進行計數
=========================================================================
對于stream()的操作,個人認為主要是對于其中的參數難以靈活使用,根據個人使用情況得到以下總結:
map()方法參數選擇:
①使用方法引用(如Role::toDTO)當轉換邏輯已經在類中存在
②使用Lambda表達式(如bizId -> new CouponScope().setBizId(bizId))當需要創建新對象或進行復雜轉換
collect()方法參數選擇:
①Collectors.toList() - 當需要保持元素順序的列表時
②Collectors.toSet() - 當需要去重元素時
③Collectors.toMap(keyMapper, valueMapper) - 當需要鍵值對結構時
④Collectors.groupingBy(classifier) - 當需要按條件分組時
⑤Collectors.groupingBy(classifier, downstream) - 當需要分組后進一步聚合時