1. 程式人生 > 實用技巧 >【java】對list集合進行去重 傳統方式 VS Lambda

【java】對list集合進行去重 傳統方式 VS Lambda

說道集合的去重,我們就肯定能想到唯一元素集合set,還有map中的key。那麼我們傳統的去重的方式肯定是要選擇set或者是map來實現了,另外在對實體物件型別進行去重的時候,我們可能會指定實體中的一個欄位,這種情況也是屬於多數的,那麼我們要怎麼實現呢?

一、傳統map實現

首先我們來看map實現,由於list內物件是不固定的,所以我這裡寫了一個通用的,按照id去重的例子:

/** * 根據屬性id去重 * @param objList 要去重的集合list * @param <E> list內容泛型 * @return 返回去重後的list
* @throws NoSuchFieldException * @throws IllegalAccessException */ public static <E> List<E> removeDuplicateId(List<E> objList) throws NoSuchFieldException, IllegalAccessException { List<E> newList = new ArrayList<>(); HashMap<String, String> map = new HashMap<>();
for (E t : objList) { // 為空則不進行比較(按需確定是否要新增) if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,"id"))) { continue; } String id = String.valueOf(getFieldValue(t,"id")); String value = map.get(id); if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 說明取到的這個name是第一次取到
map.put(id, id); newList.add(t); //newList就是我們想要的去重之後的結果 } } return newList; }

當然這裡還加入了一些自定義的配置,如欄位為空的時候就捨棄等,可以看出來都是根據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分組或者去重是會報空指標錯誤的。