Java集合——遍歷集合元素並修改


Java集合——遍歷集合元素並修改

摘要:本文主要總結了遍歷集合的方式,以及在遍歷時修改集合要注意的問題。

遍歷Collection

對List和Set的遍歷,有四種方式,下面以ArrayList為例進行說明。

1)普通for循環

代碼如下:

1 for (int i = 0; i < list.size(); i++) {
2     System.out.println(i);
3 }

如果要在普通for循環里對集合元素進行刪除操作,可能會出現問題:

 1 public static void main(String[] args) {
 2     List<Integer> list = new ArrayList<Integer>();
 3     list.add(1);
 4     list.add(2);
 5     list.add(2);
 6     list.add(4);
 7     list.add(5);
 8     for (int i = 0; i < list.size(); i++) {
 9         if (list.get(i) == 2) {
10             list.remove(i);
11         }
12     }
13     System.out.println(list);
14 }

運行結果如下:

1 [1, 2, 4, 5]

結果說明:

集合中有兩個值為2的元素,但是在代碼執行之后,值為2的元素並沒有完全移除。

原因就在於當第一次判斷 i = 1 位置上的值為2時,將這個元素刪除,導致這個位置之后的所有元素都向前挪動一個位置,導致 i = 1 位置上的值變成了后面的2。

下次遍歷時,判斷 i = 2 位置上的值,也就是4,導致2被跳過去了,從而導致最后打印的結果和預期的不一致。

改進方法是在刪除之后手動設置 i-- 即可。

2)增強for循環

代碼如下:

1 for (Integer i : list) {
2     System.out.println(i);
3 }

如果想在增強for循環里刪除或者添加集合元素,那么一定會報異常:

 1 public static void main(String[] args) {
 2     List<Integer> list = new ArrayList<Integer>();
 3     list.add(1);
 4     list.add(2);
 5     list.add(2);
 6     list.add(4);
 7     list.add(5);
 8     for (Integer i : list) {
 9         if (i == 2) {
10             list.remove(i);
11         }
12     }
13     System.out.println(list);
14 }

運行結果如下:

1 java.util.ConcurrentModificationException

結果說明:

因為增強for循環(foreach循環)本質上是隱式的iterator,由於在刪除和添加的時候會導致modCount發生變化,但是沒有重新設置expectedModCount,當你使用list.remove()后遍歷執行iterator.next()時,方法檢驗modCount的值和的expectedModCount值,如果不相等,就會報ConcurrentModificationException。

3)使用迭代器

代碼如下:

1 Iterator<String> iterator = list.iterator();
2 while (iterator.hasNext()) {
3     System.out.println(iterator.next());
4 }

如果在迭代的循化里使用list方法的add()方法和remove()方法,同樣會報錯:

 1 public static void main(String[] args) {
 2     List<Integer> list = new ArrayList<Integer>();
 3     list.add(1);
 4     list.add(2);
 5     list.add(2);
 6     list.add(4);
 7     list.add(5);
 8     Iterator<Integer> iterator = list.iterator();
 9     while (iterator.hasNext()) {
10         Integer i = (Integer) iterator.next();
11         if (i == 2) {
12             list.add(6);
13         }
14     }
15 }

運行結果如下:

1 java.util.ConcurrentModificationException

如果在迭代器的循環里使用迭代器的remove()方法,則不會報錯。

iterator()方法返回的Iterator類型的迭代器沒有提供添加的方法,但是listIterator()方法返回的ListIterator類型的迭代器提供了add()方法和set()方法。

使用迭代器刪除原數的代碼如下:

 1 public static void main(String[] args) {
 2     List<Integer> list = new ArrayList<Integer>();
 3     list.add(1);
 4     list.add(2);
 5     list.add(2);
 6     list.add(4);
 7     list.add(5);
 8     Iterator<Integer> iterator = list.iterator();
 9     while (iterator.hasNext()) {
10         Integer i = (Integer) iterator.next();
11         if (i == 2) {
12             iterator.remove();
13         }
14     }
15     System.out.println(list);
16 }

運行結果如下:

1 [1, 4, 5]

結果說明:

迭代器的remove()方法同時維護了modCount和expectedModCount,所以使用remove()方法可以達到預期的效果。

4)使用forEach方法

forEach()方法是JDK1.8新增的方法,需要配合Lambda表達式使用,代碼如下:

1 list.forEach(String -> System.out.println(String));

運行結果如下:

1 1
2 2
3 3
4 4

遍歷Map

對Map的遍歷,有四種方式,下面以HashMap為例進行說明。

1)通過keySet()方法遍歷key和value

通過keySet()方法獲取到map的所有key值,遍歷key值的集合,獲取對應的value值。代碼如下:

1 for (Integer i : map.keySet()) {
2     System.out.println(i + " >>> " + map.get(i));
3 }

運行結果如下:

1 0 >>> 000
2 1 >>> 111
3 2 >>> 222
4 3 >>> 333
5 4 >>> 444

在遍歷的時候是可以修改的,但是不能添加和刪除,否則會ConcurrentModificationException異常,代碼如下:

1 for (Integer i : map.keySet()) {
2     System.out.println(i + " >>> " + map.get(i));
3     if (map.get(i) == "222") {
4         map.put(i, "999");
5     }
6 }

運行結果如下:

1 key= 0 and value= 000
2 key= 1 and value= 111
3 key= 2 and value= 999
4 key= 3 and value= 333
5 key= 4 and value= 444

2)通過entrySet()方法遍歷key和value

這種方式同樣支持修改,但不支持添加和刪除,這種方式的效率最高,推薦使用,代碼如下:

1 for (Map.Entry<Integer, String> entry : map.entrySet()) {
2     System.out.println(entry.getKey() + " >>> " + entry.getValue());
3 }

3)通過entrySet()方法獲取迭代器遍歷key和value

這種方式同樣支持修改,但不支持添加和刪除,代碼如下:

1 Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
2 while (iterator.hasNext()) {
3     Map.Entry<Integer, String> entry = iterator.next();
4     System.out.println(entry.getKey() + " >>> " + entry.getValue());
5 }

4)通過values()方法遍歷所有的value

這種方式只能遍歷value,不能遍歷key,代碼如下:

1 for (String value : map.values()) {
2     System.out.println(value);
3 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM