Java Collection 移除元素方法及注意事項(xiàng)
1. 前言
操作集合是一個(gè) Java 編程人員幾乎每天都在重復(fù)的事情。今天我們來研究一下從 Java Collection 中刪除元素的方法。我構(gòu)建了一個(gè)簡單的集合,我們以此為例子來展開探索。
List<String> servers = new ArrayList<>(); servers.add("Felordcn"); servers.add("Tomcat"); servers.add("Jetty"); servers.add("Undertow"); servers.add("Resin");
2. for 循環(huán)并不一定能從集合中移除元素
讓我們使用傳統(tǒng)的 foreach 循環(huán)移除 F 開頭的假服務(wù)器,但是你會發(fā)現(xiàn)這種操作引發(fā)了 ConcurrentModificationException 異常。
// 錯(cuò)誤的示范 千萬不要使用 for (String server : servers) { if (server.startsWith("F")) { servers.remove(server); } }
難道 for 循環(huán)就不能移除元素了嗎?當(dāng)然不是!我們?nèi)绻艽_定需要被移除的元素的索引還是可以的。
// 這種方式是可行 for (int i = 0; i < servers.size(); i++) { if (servers.get(i).startsWith("F")) { servers.remove(i); } }
但是這種方式我目前只演示了 ArrayList,其它的類型并沒有嚴(yán)格測試,留給你自己探索。
3. 迭代器 Iterator 可以刪除集合中的元素
在傳統(tǒng)方式中我們使用 Iterator 是可以保證刪除元素的:
Iterator<String> iterator = servers.iterator(); while (iterator.hasNext()) { String next = iterator.next(); if (next.startsWith("F")) { iterator.remove(); } }
4. 遍歷刪除元素的缺點(diǎn)
- 我們需要遍歷集合的每一個(gè)元素并對它們進(jìn)行斷言,哪怕你刪除一個(gè)元素。
- 盡管我們可以通過迭代的方式刪除特定的元素,但是操作繁瑣,根據(jù)集合類型的不同有潛在的 ConcurrentModificationException 異常。
- 根據(jù)數(shù)據(jù)結(jié)構(gòu)的不同,刪除元素的時(shí)間復(fù)雜度也大大不同。比如數(shù)組結(jié)構(gòu)的 ArrayList 在刪除元素的速度上不如鏈表結(jié)構(gòu)的 LinkedList。
5. 新的集合元素刪除操作
Java 8 提供了新的集合操作 API 和 Stream 來幫助我們解決這個(gè)問題。我在以前的文章中已經(jīng)介紹了 Java 8 Stream API,如果有興趣可以去看看。
5.1 Collection.removeIf()
新的 Collection Api removeIf(Predicate<? super E> filter) 。該 Api 提供了一種更簡潔的使用 Predicate (斷言)刪除元素的方法,于是我們可以更加簡潔的實(shí)現(xiàn)開始的需求:
servers.removeIf(s-> s.startsWith("F"));
同時(shí)根據(jù)測試,ArrayList 和 LinkedList 的性能接近。一般推薦使用這種方式進(jìn)行操作。
5.2 Stream 實(shí)現(xiàn)移除元素
和上面所有移除操作不同的是,其實(shí)任何操作都不會改變 Stream 源,我們僅僅是使用 Stream Api 操作數(shù)據(jù)源的副本。遵循了 數(shù)據(jù)源 -> 中間操作 -> 歸納終止 的生命周期。我們來看看使用 Stream 如何實(shí)現(xiàn)我們的意圖。
5.2.1 通過 filter 斷言實(shí)現(xiàn)
我們可以使用 Stream 的 filter 斷言。filter 斷言會把符合斷言的流元素匯集成一個(gè)新的流,然后歸納起來即可,于是我們可以這么寫:
// 跟以上不同的是 該方式中的斷言是取反的操作。 List<String> newServers = servers.stream().filter(s -> !s.startsWith("F")).collect(Collectors.toList());
這個(gè)優(yōu)點(diǎn)上面已經(jīng)說了不會影響原始數(shù)據(jù),生成的是一個(gè)副本。缺點(diǎn)就是可能會有內(nèi)存占用問題。
5.2.2 通過 Collectors.partitioningBy 歸納
這種方法雖然可以滿足需要但是我感覺有點(diǎn)投機(jī)取巧的成份。Collectors.partitioningBy() 方法本意是做二分類的。該方法會將流中符合斷言的、不符合斷言的元素分別歸納到兩個(gè) key 分別為 true 和 false 的 Map 中,我們可以歸類得到符合和不符合的元素集。實(shí)現(xiàn)如下:
Map<Boolean, List<String>> f = servers.stream().collect(Collectors.partitioningBy(s -> !s.startsWith("F"))); List<String> trues = f.get(Boolean.TRUE); System.out.println("不以 F 開頭的: " + trues); List<String> falses = f.get(Boolean.FALSE); System.out.println("以 F 開頭的: " + falses);
一般該方式不推薦在此場景使用,并不符合該 Api 的設(shè)計(jì)意圖。
6. 總結(jié)
今天我們研究了一些從 Collections 中刪除元素的方法 及其注意事項(xiàng)。希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Java用jxl讀取excel并保存到數(shù)據(jù)庫的方法
這篇文章主要為大家詳細(xì)介紹了Java用jxl讀取excel并保存到數(shù)據(jù)庫的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10SSH框架網(wǎng)上商城項(xiàng)目第20戰(zhàn)之在線支付平臺
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第20戰(zhàn)之在線支付平臺,關(guān)于第三方支付的內(nèi)容從本文開始,感興趣的小伙伴們可以參考一下2016-06-06SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫的示例代碼
H2數(shù)據(jù)庫是一個(gè)開源的關(guān)系型數(shù)據(jù)庫,本文重點(diǎn)給大家介紹SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫的示例代碼,感興趣的朋友跟隨小編一起看看吧2022-02-02詳解SpringMVC @RequestBody接收J(rèn)son對象字符串
這篇文章主要介紹了詳解SpringMVC @RequestBody接收J(rèn)son對象字符串,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作
這篇文章主要介紹了SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10如何使用兩個(gè)棧實(shí)現(xiàn)隊(duì)列Java
這篇文章主要介紹了如何使用兩個(gè)棧實(shí)現(xiàn)隊(duì)列Java,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11springcloud連接遠(yuǎn)程nacos失敗顯示localhost服務(wù)連接失敗的問題解決
這篇文章主要介紹了springcloud連接遠(yuǎn)程nacos失敗顯示localhost服務(wù)連接失敗的問題解決,文中有詳細(xì)的代碼示例供大家參考,對大家解決問題有一定的幫助,需要的朋友可以參考下2024-03-03mybatis/mybatis-plus模糊查詢語句特殊字符轉(zhuǎn)義攔截器的實(shí)現(xiàn)
在開發(fā)中,我們通常會遇到這樣的情況。用戶在錄入信息是錄入了‘%’,而在查詢時(shí)無法精確匹配‘%’。究其原因,‘%’是MySQL的關(guān)鍵字,如果我們想要精確匹配‘%’,那么需要對其進(jìn)行轉(zhuǎn)義,本文就詳細(xì)的介紹一下2021-11-11