本篇內容介紹了“java List集合對象去重及按屬性去重的方法有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
目前創新互聯已為上1000家的企業提供了網站建設、域名、網絡空間、網站托管、服務器租用、企業網站設計、蘭坪網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發展。
這一篇文章我想寫一下List集合元素去重的8種方法,實際上通過靈活的運用、排列組合不一定是8種,可能有18種方法。
對象元素整體去重的4種方法
按照對象屬性去重的4種方法
為了在下文中進行測試內容講解,我們先做一些初始化數據
public class ListRmDuplicate { private List<String> list; private List<Player> playerList; @BeforeEach public void setup() { list = new ArrayList<>(); list.add("kobe"); list.add("james"); list.add("curry"); list.add("zimug"); list.add("zimug"); playerList= new ArrayList<>(); playerList.add(new Player("kobe","10000")); //科比萬歲 playerList.add(new Player("james","32")); playerList.add(new Player("curry","30")); playerList.add(new Player("zimug","27")); // 注意這里名字重復 playerList.add(new Player("zimug","18")); //注意這里名字和年齡重復 playerList.add(new Player("zimug","18")); //注意這里名字和年齡重復 } }
Player對象就是一個普通的java對象,有兩個成員變量name與age,實現了帶參數構造函數、toString、equals和hashCode方法、以及GET/SET方法。
下文中四種方法對List中的String類型以集合元素對象為單位整體去重。如果你的List放入的是Object對象,需要你去實現對象的equals和hashCode方法,去重的代碼實現方法和
List<String>
去重是一樣的。
第一種方法
是大家最容易想到的,先把List數據放入Set,因為Set數據結構本身具有去重的功能,所以再將SET轉為List之后就是去重之后的結果。這種方法在去重之后會改變原有的List元素順序,因為HashSet本身是無序的,而TreeSet排序也不是List種元素的原有順序。
[@Test](https://my.oschina.net/azibug) void testRemove1() { /*Set<String> set = new HashSet<>(list); List<String> newList = new ArrayList<>(set);*/ //去重并排序的方法(如果是字符串,按字母表排序。如果是對象,按Comparable接口實現排序) //List<String> newList = new ArrayList<>(new TreeSet<>(list)); //簡寫的方法 List<String> newList = new ArrayList<>(new HashSet<>(list)); System.out.println( "去重后的集合: " + newList); }
控制臺打印結果如下:
去重后的集合: [kobe, james, zimug, curry]
第二種方法
使用就比較簡單,先用stream方法將集合轉換成流,然后distinct去重,最后在將Stream流collect收集為List。
[@Test](https://my.oschina.net/azibug) void testRemove2() { List<String> newList = list.stream().distinct().collect(Collectors.toList()); System.out.println( "去重后的集合: " + newList); }
控制臺打印結果如下:
去重后的集合: [kobe, james, curry, zimug]
第三種方法這種方法利用了set.add(T)
,如果T元素已經存在集合中,就返回false。利用這個方法進行是否重復的數據判斷,如果不重復就放入一個新的newList中,這個newList就是最終的去重結果
//三個集合類list、newList、set,能夠保證順序 [@Test](https://my.oschina.net/azibug) void testRemove3() { Set<String> set = new HashSet<>(); List<String> newList = new ArrayList<>(); for (String str :list) { if(set.add(str)){ //重復的話返回false newList.add(str); } } System.out.println( "去重后的集合: " + newList); }
控制臺打印結果和第二種方法一致。
第四種方法這種方法已經脫離了使用Set集合進行去重的思維,而是使用newList.contains(T)
方法,在向新的List添加數據的時候判斷這個數據是否已經存在,如果存在就不添加,從而達到去重的效果。
//優化 List、newList、set,能夠保證順序 [@Test](https://my.oschina.net/azibug) void testRemove4() { List<String> newList = new ArrayList<>(); for (String cd:list) { if(!newList.contains(cd)){ //主動判斷是否包含重復元素 newList.add(cd); } } System.out.println( "去重后的集合: " + newList); }
控制臺打印結果和第二種方法一致。
其實在實際的工作中,按照集合元素對象整體去重的應用的還比較少,更多的是要求我們按照元素對象的某些屬性進行去重。 看到這里請大家回頭去看一下上文中,構造的初始化數據playerList
,特別注意其中的一些重復元素,以及成員變量重復。
第一種方法為TreeSet實現Comparator接口,如果我們希望按照Player的name屬性進行去重,就去在Comparator接口中比較name。下文中寫了兩種實現Comparator接口方法:
lambda表達式:(o1, o2) -> o1.getName().compareTo(o2.getName())
方法引用:Comparator.comparing(Player::getName)
@Test void testRemove5() { //Set<Player> playerSet = new TreeSet<>((o1, o2) -> o1.getName().compareTo(o2.getName())); Set<Player> playerSet = new TreeSet<>(Comparator.comparing(Player::getName)); playerSet.addAll(playerList); /*new ArrayList<>(playerSet).forEach(player->{ System.out.println(player.toString()); });*/ //將去重之后的結果打印出來 new ArrayList<>(playerSet).forEach(System.out::println); }
輸出結果如下:三個zimug因為name重復,另外兩個被去重。但是因為使用到了TreeSet,list中元素被重新排序。
Player{name='curry', age='30'} Player{name='james', age='32'} Player{name='kobe', age='10000'} Player{name='zimug', age='27'}
第二種方法這種方法是網上很多的文章中用來顯示自己很牛的方法,但是在筆者看來有點脫了褲子放屁,多此一舉。既然大家都說有這種方法,我不寫好像我不牛一樣。我為什么說這種方法是“脫了褲子放屁”?
首先用stream()把list集合轉換成流
然后用collect及toCollection把流轉換成集合
然后剩下的就和第一種方法一樣了
前兩步不是脫了褲子放屁么?看看就得了,實際應用意義不大,但是如果是為了學習Stream流的使用方法,搞出這么一個例子還是有可取之處的。
@Test void testRemove6() { List<Player> newList = playerList.stream().collect(Collectors .collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Player::getName))), ArrayList::new)); newList.forEach(System.out::println); }
控制臺打印輸出和第一種方法一樣。
第三種方法
這種方法也是筆者建議大家使用的一種方法,咋一看好像代碼量更大了,但實際上這種方法是應用比較簡單的方法。
Predicate(有人管這個叫斷言,從英文的角度作為名詞可以翻譯為謂詞,作為動詞可以翻譯為斷言)。謂詞就是用來修飾主語的,比如:喜歡唱歌的小鳥,喜歡唱歌就是謂詞,用來限定主語的范圍。所以我們這里是用來filter過濾的,也是用來限制主語范圍的,所以我認為翻譯為謂詞更合適。隨便吧,看你怎么覺得怎么理解合理、好記,你就怎么來。
首先我們定義一個謂詞Predicate用來過濾,過濾的條件是distinctByKey。謂詞返回ture元素保留,返回false元素被過濾掉。
當然我們的需求是過濾掉重復元素。我們去重邏輯是通過map的putIfAbsent實現的。putIfAbsent方法添加鍵值對,如果map集合中沒有該key對應的值,則直接添加,并返回null,如果已經存在對應的值,則依舊為原來的值。
如果putIfAbsent返回null表示添加數據成功(不重復),如果putIfAbsent返回value(value==null :false),則滿足了distinctByKey謂詞的條件元素被過濾掉。
這種方法雖然看上去代碼量增大了,但是distinctByKey謂詞方法只需要被定義一次,就可以無限復用。
@Test void testRemove7() { List<Player> newList = new ArrayList<>(); playerList.stream().filter(distinctByKey(p -> p.getName())) //filter保留true的值 .forEach(newList::add); newList.forEach(System.out::println); } static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) { Map<Object,Boolean> seen = new ConcurrentHashMap<>(); //putIfAbsent方法添加鍵值對,如果map集合中沒有該key對應的值,則直接添加,并返回null,如果已經存在對應的值,則依舊為原來的值。 //如果返回null表示添加數據成功(不重復),不重復(null==null :TRUE) return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; }
輸出結果如下:三個zimug因為name重復,另外兩個被去重。并且沒有打亂List的原始順序
Player{name='kobe', age='10000'} Player{name='james', age='32'} Player{name='curry', age='30'} Player{name='zimug', age='27'}
第四種方法第四種方法實際上不是新方法,上面的例子都是按某一個對象屬性進行去重,如果我們想按照某幾個元素進行去重,就需要對上面的三種方法進行改造。 我只改造其中一個,另外幾個改造的原理是一樣的,就是把多個比較屬性加起來,作為一個String屬性進行比較。
@Test void testRemove8() { Set<Player> playerSet = new TreeSet<>(Comparator.comparing(o -> (o.getName() + "" + o.getAge()))); playerSet.addAll(playerList); new ArrayList<>(playerSet).forEach(System.out::println); }
“java List集合對象去重及按屬性去重的方法有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注創新互聯網站,小編將為大家輸出更多高質量的實用文章!
當前標題:javaList集合對象去重及按屬性去重的方法有哪些
分享鏈接:http://m.newbst.com/article28/gpgicp.html
成都網站建設公司_創新互聯,為您提供網站設計公司、關鍵詞優化、網站維護、商城網站、做網站、網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯