【java】對list集合進行去重 傳統方式 VS Lambda
說道集合的去重,我們就肯定能想到唯一元素集合set,還有map中的key。那麼我們傳統的去重的方式肯定是要選擇set或者是map來實現了,另外在對實體物件型別進行去重的時候,我們可能會指定實體中的一個欄位,這種情況也是屬於多數的,那麼我們要怎麼實現呢?
一、傳統map實現
首先我們來看map實現,由於list內物件是不固定的,所以我這裡寫了一個通用的,按照id去重的例子:
/** * 根據屬性id去重 * @param objList 要去重的集合list * @param <E> list內容泛型 * @return 返回去重後的list當然這裡還加入了一些自定義的配置,如欄位為空的時候就捨棄等,可以看出來都是根據map特性,如果在map中找到了值,則不再add。
如果擴充套件成根據指定欄位去重,則程式碼修改為把欄位的string傳入即可:
public static <E> List<E> removeDuplicateId(List<E> objList,String filedName) throws NoSuchFieldException, IllegalAccessException {if (StringUtils.isBlank(filedName)){
return objList;
}
List<E> newList = new ArrayList<>();
HashMap<String, String> map = new HashMap<>();
for (E t : objList) {
// 為空則不進行比較(按需確定是否要新增)
if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,filedName))) {
continue;
}
String id = String.valueOf(getFieldValue(t,filedName));
String value = map.get(id);
if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 說明取到的這個name是第一次取到
map.put(id, id);
newList.add(t); //newList就是我們想要的去重之後的結果
}
}
return newList;
}
如果要根據多個欄位去重,需要怎樣呢?擴充套件第二個引數為字元陣列即可:
public static <E> List<E> removeDuplicateId(List<E> objList,String... filedNames) throws NoSuchFieldException, IllegalAccessException {if (filedNames==null||filedNames.length==0){
return objList;
}
List<E> newList = new ArrayList<>();
HashMap<String, String> map = new HashMap<>();
for (E t : objList) {
String key = "";
for (int i = 0; i < filedNames.length; i++) {
key += String.valueOf(getFieldValue(t,filedNames[i]));
}
String value = map.get(key);
if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 說明取到的這個name是第一次取到
map.put(key, key);
newList.add(t); //newList就是我們想要的去重之後的結果
}
}
return newList;
}
有了map的實現,set的也不難了,只需要把裡面判斷和新增map的程式碼修改為set物件即可。
二、labmda實現
lambda實現就比較簡單了,看一下三連:
單個欄位去重:
List<Member> memberList= members.stream() .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()))), ArrayList::new));
多個欄位去重:
List<Member> memberList = members.stream() .collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()+"-"+member.getId()))), ArrayList::new));
還有一個根據某個或者幾個欄位分組,也可以滿足這種需求:
Map<String,List<Member>> map = members.stream().collect(Collectors.groupingBy(Member::getName));
三、總結
相比較來說,使用lambda進行去重,寫法比較簡單,程式碼簡潔有利於閱讀,而傳統方式則過於繁瑣,需要寫專門的util進行處理,但是從另外的角度來講傳統方式比較靈活,可以增加lambda沒有的判斷,如果需要去重的欄位有為null的情況,使用lambda分組或者去重是會報空指標錯誤的。