List對象集合根據組合屬性進行差集運算


背景

   當List是一個基本數據類型的集合的時候,進行集合運算還比較方便,但是有這么一些業務場景,比如某個用戶權限變化的列表,或者取數據的變化結果,當時有時候用笨方法多循環兩次也是可以的,只不過代碼顯得比較復雜,而且性能也不會太好。這次迭代我也就遇到這么一個需求。

實現

   場景:我們系統用戶是四個維度這樣的數據,我們需要保存這樣的數據,提供給前端一個這樣的接口,前端傳遞用戶相應的數據(用戶組|職位|部門|用戶),但是前端不會告訴我們,哪些是新增的,哪些是刪除的,還有哪些沒有變化,反正數據一股腦的給你,后端來自己組織。​當然,一般第一想法都是循環嘛,但是我一般的習慣都是將這種處理方法放在最后一個備選,實在想不出來好的方式才會使用最簡單粗暴的方式哈哈哈。而且這個地方是要根據實體類里面的兩個字段一起判斷,無形中增加復雜度。List可以這樣求差集(交並集類似):

// 差集
List<String> subList = list1.stream().filter(item -> list2.contains(item)).collect(toList());

   但這個List就一個String類型的,方便,而我們要判斷的是兩個對象是不是相等,簡單嘛,一樣這樣使用嘛,那萬一兩個對象並不相同的,比如一個列表是從數據庫中取出來的值,一個傳出來的,它們的字段值都不同,那他們equals肯定也不同的,過濾后的值也不同,就會造成數據錯誤。

// 考慮過濾數據,不進行重復更新
List<SaveLibUserParam> saveLibUserParamList = param.getSaveLibUserParamList();
List<UserCourseLibraryManage> originSaveList = Lists.newArrayList();
if (Objects.nonNull(saveLibUserParamList) && saveLibUserParamList.size() > 0) {
originSaveList = BeanConvertUtils.convertList(saveLibUserParamList, UserCourseLibraryManage.class);
}
// 查詢出本來的舊數據
List<UserCourseLibraryManage> list = userCourseLibraryManageDao.queryListByCompanyId(companyId);
log.info("originList:{}", originSaveList);
log.info("list:{}", list);
// 需要本次新增的,即在origin中而list沒有的
// 需要本次刪除的,即在origin沒有而list中有的
List<UserCourseLibraryManage> needAddList = originSaveList.stream().filter(item -> !list.contains(item)).collect(Collectors.toList());
List<UserCourseLibraryManage> finalOriginSaveList = originSaveList;
List<UserCourseLibraryManage> deleteList = list.stream().filter(item -> !finalOriginSaveList.contains(item)).collect(Collectors.toList());
log.info("needAddList:size:{}, data:{}", needAddList.size(), needAddList);
log.info("deleteList:size:{}, data:{}", deleteList.size(), deleteList);

   所以要考慮判斷兩個對象相等的條件,這里大家應該都知道了,就是重寫equals方法,判斷對象中值相等用equals方法,不用用\(==\)符號,\(==\)符號在判斷對象類型時判斷的是地址,這個地方需要注意的。對上面的UserCourseLibraryManage實體對象進行重寫equals,在重寫equals的時候,一定要注意:hashCode一般也建議重寫,以保證兩個對象的hash值一致,只有當對象的hash值一致時,系統才會判定這兩個對象相等。重寫hashcode的時候為什么用17,網上說好像Jdk就用的17,還有待考證,反正保證不要超出int范圍就可以。

/**
* 重寫equals方法
* @param obj
* @return
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof UserCourseLibraryManage) {
if (Objects.equals(((UserCourseLibraryManage) obj).dataType, this.dataType)
&& Objects.equals(((UserCourseLibraryManage) obj).dataId, this.dataId)) {
// System.out.println("相同對象:obj:"+obj+", this:{}"+this+"");
return true;
} else {
return false;
}
} else {
return super.equals(obj);
}
}

/**
* 重寫hashcode
* @return
*/
@Override
public int hashCode() {
int newHashCode = dataType.hashCode();
newHashCode = 17 * newHashCode + dataId.hashCode();
return newHashCode;
}

   這樣處理了一番過后,過濾處理后的數據就是我們想要的數據,達到了目的,並且性能也肯定得到了提升,使用的java8的流處理。

tips:上面list.stream處理的地方求差集用list自己的removeAll也是可以的。有興趣的可以看下源碼,但removeAll會將原數據集合改變。

   希望以后如果有小伙伴遇到這種問題,剛好不太了解如何處理,希望這個分享能有一定的幫助!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM