Java集合框架之List介面

来源:http://www.cnblogs.com/huangminwen/archive/2016/12/23/6209461.html
-Advertisement-
Play Games

在上一篇Java集合框架之Collection介面中我們知道List介面是Collection介面的子介面,List介面對Collection進行了簡單的擴充,List介面中的元素的特點為有序,可重覆,允許null值,因為List繼承了Collection介面,所以繼承自Collection介面中的 ...


在上一篇Java集合框架之Collection介面中我們知道List介面是Collection介面的子介面,List介面對Collection進行了簡單的擴充,List介面中的元素的特點為有序,可重覆,允許null值,因為List繼承了Collection介面,所以繼承自Collection介面中的方法不再贅述,從List介面中的方法來看,List介面主要是增加了面向位置的操作,允許在指定位置上對集合中的元素進行操作,同時增加了一個能夠雙向遍歷線性表的新列表迭代器ListIterator。下麵介紹List介面中的方法

1、添加

void add(int index,E element):在指定位置添加元素

boolean addAll(int index,Collection<? extends E> c),在指定的位置添加一個集合的元素

示例代碼

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo1 {
 7     public static void main(String[] args) {
 8         List list1 = new ArrayList();
 9         list1.add("紅樓夢");
10         list1.add("三國演義");
11         list1.add("三國演義");
12         list1.add(null);
13         System.out.println("集合的長度:" + list1.size());
14 
15         list1.add(1, "平凡的世界");
16         System.out.println(list1);
17 
18         List list2 = new ArrayList();
19         list2.add("西游記");
20         list2.add("水滸傳");
21         list1.add(1, list2);
22         System.out.println(list1);
23     }
24 }

輸出結果

集合的長度:4
[紅樓夢, 平凡的世界, 三國演義, 三國演義, null]
[紅樓夢, [西游記, 水滸傳], 平凡的世界, 三國演義, 三國演義, null]

可以看到List中有重覆的元素以及null元素,如果指定的位置超過了集合的長度,則會報IndexOutOfBoundsException異常,如下

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo1 {
 7     public static void main(String[] args) {
 8         List list = new ArrayList();
 9         list.add("紅樓夢");
10         list.add("三國演義");
11         list.add("西游記");
12         list.add("水滸傳");
13         System.out.println("集合的長度:" + list.size());
14 
15         list.add(5, "平凡的世界"); // 超過了集合的最大長度
16         System.out.println(list);
17     }
18 }

控制台輸出結果

集合的長度:4
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 4
    at java.util.ArrayList.rangeCheckForAdd(Unknown Source)
    at java.util.ArrayList.add(Unknown Source)
    at list.ListDemo1.main(ListDemo1.java:15)

以下講述的方法中,凡是涉及到位置的方法,如果指定的位置超過了集合的最大長度,則同樣報IndexOutOfBoundsException異常。

2、獲取

E get(int index):返回指定位置的元素

int indexOf(Object o):返回此列表中第一次出現的指定元素的索引;如果此列表不包含該元素,則返回 -1

int lastIndexOf(Object o):返回此列表中最後出現的指定元素的索引;如果列表不包含此元素,則返回 -1

List<E> subList(int fromIndex,int toIndex):返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之間的部分視圖。(如果 fromIndex 和 toIndex 相等,則返回的列表為空)

示例代碼

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo2 {
 7     public static void main(String[] args) {
 8         List list = new ArrayList();
 9         list.add("紅樓夢");
10         list.add("三國演義");
11         list.add("西游記");
12         list.add("水滸傳");
13         list.add("紅樓夢");
14 
15         Object object = list.get(0);
16         System.out.println(object);
17 
18         int index = list.indexOf("紅樓夢");
19         System.out.println("第一次出現紅樓夢的索引:" + index);
20 
21         index = list.indexOf("平凡的世界");
22         System.out.println("第一次出現平凡的世界的索引:" + index);
23 
24         index = list.lastIndexOf("紅樓夢");
25         System.out.println("最後一次出現紅樓夢的索引:" + index);
26 
27         index = list.lastIndexOf("平凡的世界");
28         System.out.println("最後一次出現平凡的世界的索引:" + index);
29 
30         list = list.subList(1, 3); // 不包括3位置的元素
31         System.out.println(list);
32     }
33 }

輸出結果

紅樓夢
第一次出現紅樓夢的索引:0
第一次出現平凡的世界的索引:-1
最後一次出現紅樓夢的索引:4
最後一次出現平凡的世界的索引:-1
[三國演義, 西游記]

3、刪除

E remove(int index):移除列表中指定位置的元素(可選操作)。將所有的後續元素向左移動(將其索引減 1)。返回從列表中移除的元素。

示例代碼

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo3 {
 7     public static void main(String[] args) {
 8         List list = new ArrayList();
 9         list.add("紅樓夢");
10         list.add("三國演義");
11         list.add("西游記");
12         list.add("水滸傳");
13         
14         int index = list.indexOf("西游記");
15         System.out.println("西游記原來的索引:" + index);
16         
17         Object object = list.remove(1);
18         System.out.println("刪除的元素: " + object);
19         
20         index = list.indexOf("西游記");
21         System.out.println("移除元素之後西游記的索引:" + index);
22         
23         System.out.println(list);
24     }
25 }

輸出結果

西游記原來的索引:2
刪除的元素: 三國演義
移除元素之後西游記的索引:1
[紅樓夢, 西游記, 水滸傳]

4、賦值

E set(int index,E element):用指定元素替換列表中指定位置的元素(可選操作)。

代碼示例

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo4 {
 7     public static void main(String[] args) {
 8         List list = new ArrayList();
 9         list.add("紅樓夢");
10         list.add("三國演義");
11         list.add("西游記");
12         list.add("水滸傳");
13         list.set(0, "平凡的世界");
14         System.out.println(list);
15     }
16 }

輸出結果

[平凡的世界, 三國演義, 西游記, 水滸傳]

5、遍歷

ListIterator<E> listIterator():返回此列表元素的列表迭代器(按適當順序)。

ListIterator是一個介面,繼承自Iterator介面,除了擁有Iterator介面中的方法之外,還擁有一些自己特有的方法

boolean hasPrevious():逆向遍歷列表,如果仍有元素可以迭代,則返回 true。

E previous():返回迭代的上一個元素,並移動到上一個位置。

雖然ListIterator可以實現集合的逆向迭代,但是從Java集合框架之Collection介面中我們知道,迭代器初始狀態下前面並沒有任何元素,必須先正向遍歷,才能逆向遍歷,所以一般不使用逆向迭代。

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.ListIterator;
 6 
 7 public class ListDemo5 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("西游記");
13         list.add("水滸傳");
14 
15         ListIterator it = list.listIterator();
16         
17         System.out.println("----------逆向迭代----------");
18         while (it.hasPrevious()) {
19             Object object = (Object) it.previous();
20             System.out.println(object);
21         }
22 
23         System.out.println("----------正向迭代----------");
24         while (it.hasNext()) {
25             Object object = it.next();
26             System.out.println(object);
27         }
28         
29         System.out.println("----------逆向迭代----------");
30         while (it.hasPrevious()) {
31             Object object = (Object) it.previous();
32             System.out.println(object);
33         }
34     }
35 }

輸出結果

----------逆向遍歷----------
----------正向遍歷----------
紅樓夢
三國演義
西游記
水滸傳
----------逆向遍歷----------
水滸傳
西游記
三國演義
紅樓夢

從上面結果可以看出,當第一次逆向迭代的時候並沒有任何輸出,當正向迭代後,迭代器到了集合的末尾之後,再次逆向迭代,這時才有輸出。

上面的while迴圈,我們可以改成for迴圈

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.List;
 6 
 7 public class ListDemo6 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("西游記");
13         list.add("水滸傳");
14 
15         for (Iterator iterator = list.iterator(); iterator.hasNext();) {
16             Object object = (Object) iterator.next();
17             System.out.println(object);
18         }
19     }
20 }

在效率上,或許for迴圈的更高,因為for迴圈結束之後iterator變數的作用域便結束了,iterator變數就消失了。我們還可以結合get(int index)與size()方法來遍歷集合

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class ListDemo7 {
 7     public static void main(String[] args) {
 8         List list = new ArrayList();
 9         list.add("紅樓夢");
10         list.add("三國演義");
11         list.add("西游記");
12         list.add("水滸傳");
13 
14         for (int i = 0; i < list.size(); i++) {
15             Object object = list.get(i);
16             System.out.println(object);
17         }
18     }
19 }

下麵再來看ListIterator中對元素進行操作的方法

void add(E e):將指定的元素插入列表

void remove():從列表中移除由 next 或 previous 返回的最後一個元素

void set(E e):用指定元素替換 next 或 previous 返回的最後一個元素

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.ListIterator;
 6 
 7 public class ListDemo8 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("西游記");
13         list.add("水滸傳");
14 
15         ListIterator it = list.listIterator();
16 
17         it.add("平凡的世界");
18 
19         System.out.println(list);
20 
21         it.next();
22         it.remove(); // 調用remove方法時需要先調用next或
23                         // previous方法,否則將拋出java.lang.IllegalStateException異常
24         it.next();
25         it.set("新三國演義");// 調用remove方法時需要先調用next或
26                         // previous方法,否則將拋出java.lang.IllegalStateException異常
27 
28         System.out.println(list);
29     }
30 }

輸出結果

[平凡的世界, 紅樓夢, 三國演義, 西游記, 水滸傳]
[平凡的世界, 新三國演義, 西游記, 水滸傳]
西游記
水滸傳

有時候我們在操作集合的時候,需要對集合的元素進行添加或者是刪除

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.List;
 6 
 7 public class ListDemo9 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("水滸傳");
13 
14         Iterator it = list.iterator();
15 
16         while (it.hasNext()) {
17             String s = (String) it.next();
18             if ("三國演義".equals(s)) {
19                 list.add("西游記");
20             }
21         }
22 
23         System.out.println(list);
24     }
25 }

運行這段程式,控制台將出現如下錯誤

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at list.ListDemo9.main(ListDemo9.java:17)

ConcurrentModificationException:當方法檢測到對象的併發修改,但不允許這種修改時,拋出此異常。 為什麼會出現這種錯誤呢,這是因為迭代器是依賴於集合而存在的,在判斷成功後,集合中新添加了元素,而迭代器這時還不知道,所以就報錯了,這個錯叫併發修改異常。報錯的地方為代碼17行,正是迭代器獲取元素的時候。如何解決這個問題呢,既然迭代器遍歷集合的時候,集合不能對元素進行操作,那麼使用迭代器操作元素呢

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.ListIterator;
 6 
 7 public class ListDemo10 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("水滸傳");
13 
14         ListIterator it = list.listIterator();
15 
16         while (it.hasNext()) {
17             String s = (String) it.next();
18             if ("三國演義".equals(s)) {
19                 it.add("西游記");
20             }
21         }
22 
23         System.out.println(list);
24     }
25 }

這時候控制台的沒有報錯了

[紅樓夢, 三國演義, 西游記, 水滸傳]

用迭代器添加的元素時,元素的位置為當前迭代器的位置,換個角度想一下,既然迭代器遍歷集合的時候,迭代器可以對集合的元素進行操作,那麼集合遍歷元素的時候,集合是否也可以對元素進行操作呢

 1 package list;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.ListIterator;
 6 
 7 public class ListDemo10 {
 8     public static void main(String[] args) {
 9         List list = new ArrayList();
10         list.add("紅樓夢");
11         list.add("三國演義");
12         list.add("水滸傳");
13 
14         for (int i = 0; i < list.size(); i++) {
15             if ("水滸傳".equals(list.get(i))) {
16                 list.add("西游記");
17             }
18         }
19 
20         System.out.println(list);
21     }
22 }

輸出結果

[紅樓夢, 三國演義, 水滸傳, 西游記]

當用集合添加元素的時候,添加在了集合的最後面

由上述結果可以知,有兩種方法可以解決併發修改異常ConcurrentModificationException

1、迭代器迭代元素,迭代器修改元素

2、集合遍歷元素,集合修改元素(普通for)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #region 發送郵件 //填寫電子郵件地址,和顯示名稱 System.Net.Mail.MailAddress from = new System.Net.Mail.MailAddress("[email protected]", "wode"); //填寫郵件的收件人地址和名稱 ... ...
  • 瞭解過入口函數 Main() 嗎?帶你用批處理玩轉 Main 函數 目錄 簡介 特點 方法的參數 方法的返回值 與批處理交互的一個示例 簡介 我們知道,新建一個控制台應用程式的時候,IDE 會同時創建一個預設的類 Program.cs,該類會包含一個 Main 方法。我們在直接 F5 的時候就會立即 ...
  • 1、ViewBag Controller:ViewBag.Message = "Hello, Word"; View:@ViewBag.Message 註:ViewBag的類型是動態的,不確定的,直接就可以使用,它的傳值範圍是:controller向view傳值,view自己和自己傳值。2、View ...
  • 實現效果如下: 1.在前臺Web的Category Menu顯示 Vendor; 2.點擊Vendor 顯示Vendor List列表; 主要配置步驟: 1.運行網站 Admin 後臺 Categorys 增加 Vendor 並配置其SEO 如vendor-all 2.代碼層面 Nop.Web In ...
  • 然ASP.NET Core應用的路由是通過RouterMiddleware這個中間件來完成的,但是具體的路由解析功能都落在指定的Router對象上,不過我們依然有必要以代碼實現的角度來介紹一下這個中間件。 ...
  • 有時需要追求效率,會代替一些算術運算。 求商:a >> n <=> a / 2^n 求積:a << n <=> a * 2^n 求餘:a & ((1 << n) - 1) <=> a % 2^n 奇偶判斷:a & 1 == 1 <==> a % 2 == 1 一般1表示選中或者開啟項,0表示未選或者 ...
  • 背景 由於工作的一些原因,需要從C#轉成JAVA。之前PetaPoco用得真是非常舒服,在學習JAVA的過程中熟悉了一下JAVA的數據組件: MyBatis 非常流行,代碼生成也很成熟,性能也很好。但是DEBUG的時候不方便,且XML寫SQL也不是很適應,尤其是團隊比較小沒有專職DBA的情況下。 H ...
  • 使用對象來管理資源,可以避免因個人疏忽帶來的一些低級錯誤,但是不是每件事都是稱心如意的。 一些函數依然使用原始的資源對象,那麼我們就需要為這些函數提供一個介面,讓他們可以獲取到原始對象。 繼續拿13節的智能指針說事,先上代碼: //SFAutoPtr.h #pragma once template ... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...