Java如何在List或Map遍历过程中删除元素

遍历删除List或Map中的元素有很多种方法,当运用不当的时候就会产生问题。下面通过这篇文章来再学习学习吧。

一、List遍历过程中删除元素

使用索引下标遍历的方式

示例:删除列表中的2

public static void main(String[] args) {
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);

  for (int i = 0; i < list.size(); i++) {
   if(2 == list.get(i)){
    list.remove(i);
   }
   System.out.println(list.get(i));
  }

  System.out.println("list=" + list.toString());

 }

输出结果:

1
2
3
4
list=[1, 2, 3, 4]

问题:

结果显示只删除了一个2,另一个2被遗漏了,原因是:删除了第一个2后,集合里的元素个数减1,后面的元素往前移了1位,导致了第二个2被遗漏了。

使用For循环遍历的方式

示例:

public static void listIterator2(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);

  for (int value : list) {
   if(2 == value){
    list.remove(value);
   }
   System.out.println(value);
  }

  System.out.println("list=" + list.toString());

 }

结果:

Exception in thread "main" 1
2
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at test.ListIterator.listIterator2(ListIterator.java:39)
 at test.ListIterator.main(ListIterator.java:10)

说明:

jdk中对ConcurrentModificationException的描述:

public class ConcurrentModificationException extends

RuntimeException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。

注意:此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。

注意:迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。

Java中的For each实际上使用的是iterator进行处理的。而iterator是不允许集合在iterator使用期间删除的。所以导致了iterator抛出了ConcurrentModificationException

正确的方式

示例:

public static void listIterator3(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);

  Iterator<Integer> it = list.iterator();
  while (it.hasNext()){
   Integer value = it.next();
   if (2 == value) {
    it.remove();
   }

   System.out.println(value);
  }

  System.out.println("list=" + list.toString());
 }

结果:

1
2
2
3
4
list=[1, 3, 4]

二、Map遍历过程中删除元素

正确做法的示例:

public static void main(String[] args) {
 HashMap<String, String> map = new HashMap<String, String>();
 map.put("1", "test1");
 map.put("2", "test2");
 map.put("3", "test3");
 map.put("4", "test4");

 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }

 //删除元素
 Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
 while(it.hasNext())
 {
  Map.Entry<String, String> entry= it.next();
  String key= entry.getKey();
  int k = Integer.parseInt(key);
  if(k%2==1)
  {
   System.out.printf("delete key:%s value:%s\r\n", key, entry.getValue());
   it.remove();
  }
 } 

 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }
}

结果:

key: 1 value:test1
key: 2 value:test2
key: 3 value:test3
key: 4 value:test4
delete key:1 value:test1
delete key:3 value:test3
key: 2 value:test2
key: 4 value:test4

注意

但对于iterator的remove()方法,也有需要我们注意的地方:

每调用一次iterator.next()方法,只能调用一次remove()方法。

调用remove()方法前,必须调用过一次next()方法。

JDK-API中对于remove()方法的描述:

void remove()从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的集合,则迭代器的行为是不明确的。

抛出:UnsupportedOperationException - 如果迭代器不支持 remove 操作。IllegalStateException - 如果尚未调用 next 方法,或者在上一次调用 next 方法之后已经调用了remove 方法。

总结

以上就是关于List与Map的遍历过程中删除元素的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • Java concurrency集合之ConcurrentSkipListMap_动力节点Java学院整理

    ConcurrentSkipListMap介绍 ConcurrentSkipListMap是线程安全的有序的哈希表,适用于高并发的场景. ConcurrentSkipListMap和TreeMap,它们虽然都是有序的哈希表.但是,第一,它们的线程安全机制不同,TreeMap是非线程安全的,而ConcurrentSkipListMap是线程安全的.第二,ConcurrentSkipListMap是通过跳表实现的,而TreeMap是通过红黑树实现的. 关于跳表(Skip List),它是平衡树的一种

  • 详解Java中list,set,map的遍历与增强for循环

    详解Java中list,set,map的遍历与增强for循环 Java集合类可分为三大块,分别是从Collection接口延伸出的List.Set和以键值对形式作存储的Map类型集合. 关于增强for循环,需要注意的是,使用增强for循环无法访问数组下标值,对于集合的遍历其内部采用的也是Iterator的相关方法.如果只做简单遍历读取,增强for循环确实减轻不少的代码量. 集合概念: 1.作用:用于存放对象 2.相当于一个容器,里面包含着一组对象,其中的每个对象作为集合的一个元素出现 3.jav

  • Struts2中ognl遍历数组,list和map方法详解

    一.简介 <s:iterator />可以遍历数据栈里面的任何数组,集合等等 在使用这个标签的时候有三个属性值得我们关注 1. value属性:可选的属性,value属性是指一个被迭代的集合,使用ognl表达式指定,如果为空的话默认就是ValueStack栈顶的集合. 2.id属性:可选属性, 是指集合元素的id 3.status属性:可选属性,该属性在迭代时会产生一个IteratorStatus对象,该对象可以判断当前元素的位置,包含了以下属性方法: int getCount(); 迭代元素

  • 详解 Spring注解的(List&Map)特殊注入功能

    详解 Spring注解的(List&Map)特殊注入功能 最近接手一个新项目,已经没有原开发人员维护了.项目框架是基于spring boot进行开发.其中有两处Spring的注解花费了大量的时间才弄明白到底是怎么用的,这也涉及到spring注解的一个特殊的注入功能. 首先,看到代码中有直接注入一个List和一个Map的.示例代码如下: @Autowired private List<DemoService> demoServices; @Autowired private Map<

  • java list,set,map,数组间的相互转换详解

    java list,set,map,数组间的相互转换详解 1.list转set Set set = new HashSet( new ArrayList()); 2.set转list List list = new ArrayList( new HashSet());  3.数组转为list List stooges = Arrays.asList( "Larry" , "Moe" , "Curly" ); 此时stooges中有有三个元素.注意

  • 详解javaweb中jstl如何循环List中的Map数据

    详解javaweb中jstl如何循环List中的Map数据 第一种方式: 1:后台代码(测试) List<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); Map<String, Object> map = null; for (int i = 0; i < 4; i++) { map = new HashMap<String, Object>();

  • jstl之map,list访问遍历以及el表达式map取值的实现

    场景: request域里的数据为Map<Role, Map<String, List<Menu>>>,Role为枚举类型,为用户的Role那么访问遍历如下: <c:set var="user" value="${session_usr_key}" /> <c:forEach items="${roleMenuMap[user.role]}" var="entry">

  • java 三种将list转换为map的方法详解

    java 三种将list转换为map的方法详解 在本文中,介绍三种将list转换为map的方法: 1) 传统方法 假设有某个类如下 class Movie { private Integer rank; private String description; public Movie(Integer rank, String description) { super(); this.rank = rank; this.description = description; } public Int

  • Java如何在List或Map遍历过程中删除元素

    遍历删除List或Map中的元素有很多种方法,当运用不当的时候就会产生问题.下面通过这篇文章来再学习学习吧. 一.List遍历过程中删除元素 使用索引下标遍历的方式 示例:删除列表中的2 public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(2); list.add(3); list.add(

  • Java使用entrySet方法获取Map集合中的元素

    本文为大家分享了使用entrySet方法获取Map集合中元素的具体代码,供大家参考,具体内容如下 /*--------------------------------- 使用entrySet方法取出Map集合中的元素: ....该方法是将Map集合中key与value的关系存入到了Set集合中,这个关系的数据类型是Map.Entry ....entrySet方法返回值类型的具体写法为:Set< Map.Entry<KeyType , ValueType> > -----------

  • Java使用keySet方法获取Map集合中的元素

    本文为大家分享了Map集合中利用keySet方法获取所有的元素值,供大家参考,具体内容如下 /*--------------------------- Map集合中利用keySet方法获取所有的元素值: ....keySet方法:将Map中的所有key值存入到Set集合中, ....利用Set集合提供的迭代器获取到每一个key值,再通过key值获得相应的value值 ----------------------------*/ package pack03; import java.util.*

  • java 键盘输入一个数,输出数组中指定元素的示例

    如下所示: package com.lcn.day05; import java.util.Scanner; public class ArrayDemo7 { /** *键盘输入一个数,输出数组中指定元素 */ public static void main(String[] args) { // 定义一个数组 int[] array = new int[]{123,456,789,321,654,987}; //创建输入对象 Scanner sc = new Scanner(System.i

  • java迭代器中删除元素的实例操作详解

    我们知道通过Iterator,可以对集合中的元素进行遍历.那么在其中遇到我们不需要的元素时,可不可以在遍历的时候顺便给删除呢?答案是当然可以.在Iterator下有一个remove函数,专门用于删除的操作.下面我们就remove进行讲解,然后对删除元素方法进行说明,最后带来实例的展示. 1.Iterator中的remove void remove():删除迭代器刚越过的元素 从基础集合中移除这个迭代器返回的最后一个元素(可选操作).两个线程中都删除,保证线程的同步. 2.删除元素说明 (1)迭代

  • Java封装数组实现包含、搜索和删除元素操作详解

    本文实例讲述了Java封装数组实现包含.搜索和删除元素操作.分享给大家供大家参考,具体如下: 前言:在上一小节中我们已经会了如何获取和如何修改数组中的元素,在本小节中我们将继续学习如何判断某个元素是否在数组中存在.查询出某个元素在数组中的位置.以及删除数组中元素等方法的编写. 1.查找数组中是否包含元素e,返回true或false //查找数组中是否包含元素e public boolean contains(int e) { for (int i = 0; i < size; i++) { if

  • python实现从字典中删除元素的方法

    本文实例讲述了python实现从字典中删除元素的方法.分享给大家供大家参考.具体分析如下: python的字典可以通过del方法进行元素删除,下面的代码详细演示了这一过程 # Create an empty dictionary d = {} # Add an item d["name"] = "Fido" assert d.has_key("name") # Delete the item del d["name"] ass

  • PHP从数组中删除元素的四种方法实例

    茴香豆的"茴"字有四种写法,PHP从数组中删除元素也有四种方法 ^_^. 删除一个元素,且保持原有索引不变 使用 unset 函数,示例如下: <?php $array = array(0 => "a", 1 => "b", 2 => "c"); unset($array[1]); //↑ 你想删除的key ?> 输出: Array (     [0] => a     [2] =>

  • php数组中删除元素之重新索引的方法

    如果要在某个数组中删除一个元素,可以直接用的unset,但今天看到的东西却让我大吃一惊 复制代码 代码如下: <?php $arr = array('a','b','c','d'); unset($arr[1]); print_r($arr); ?> print_r($arr)之后,结果却不是那样的,最终结果是 Array ( [0] => a [2] => c [3] => d ) 那么怎么才能做到缺少的元素会被填补并且数组会被重新索引呢?答案是 array_splice(

  • Java函数式编程(四):在集合中查找元素

    查找元素 现在我们对这个设计优雅的转化集合的方法已经不陌生了,但它对查找元素却也是无能为力.不过filter方法却是为这个而生的. 我们现在要从一个名字列表中,取出那些以N开头的名字.当然可能一个也没有,结果可能是个空集合.我们先用老方法实现一把. 复制代码 代码如下: final List<String> startsWithN = new ArrayList<String>(); for(String name : friends) { if(name.startsWith(&

随机推荐