问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

java中的List和Map和方法有哪几种?

发布网友 发布时间:2022-04-21 19:08

我来回答

2个回答

热心网友 时间:2024-03-05 01:34

(一)List的遍历方法及如何实现遍历删除
我们造一个list出来,接下来用不同方法遍历删除,如下代码:
List<String> list= new ArrayList<String>();famous.add("zs");famous.add("ls");famous.add("ww");famous.add("dz");

1、for循环遍历list:
for(int i=0;i<list.size();i++){if(list.get(i).equals("ls"))list.remove(i);}

这是一种很常见的遍历方式,但是使用这种遍历删除元素会出现问题,原因在于删除某个元素后,list的大小发生了变化,而你的索引
也在变化,所以会导致你在遍历的时候漏掉某些元素。比如当你删除第一个元素后,继续根据索引访问第二个元素后,因为删除的原因,
后面的元素都往前移动了以为,所以实际访问的是第三个元素。因此,这种遍历方式可以用在读取元素,而不适合删除元素。
2、增强for循环:
for(String x:list){if(x.equals("ls"))list.remove(x);}

这也是一种很常见的遍历方式,但是使用这种遍历删除元素也会出现问题,运行时会报ConcurrentModificationException异常
其实增强for循环是java语法糖的一种体现,如果大家通过反编译得到字节码,那么上面这段代码的内部实现如下所示:

for(Iterator<String> it = list.iterator();it.hasNext();){String s = it.next();if(s.equals("madehua")){list.remove(s);}}

下面就解释为什么会报ConcurrentModificationException异常。分析Iterator的源代码,重点分析整个调用该过程中的
函数(hasNext和remove):

private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;public boolean hasNext() {return cursor != size; // size为集合中元素的个数}public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}/* 此方法并没被调用,只是调用List.remove方法 public void remove() { checkForComodification(); try { ArrayList.this.remove(lastRet);// size字段减1 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } */final void checkForComodification() {// 检查修改和当前版本号是否一致,不一致则抛出异常if (modCount != expectedModCount)throw new ConcurrentModificationException();} } // List.remove @Override public boolean remove(Object object) {Object[] a = array;int s = size;if (object != null) {for (int i = 0; i < s; i++) {if (object.equals(a[i])) {System.arraycopy(a, i + 1, a, i, --s - i);a[s] = null; // Prevent memory leaksize = s;modCount++;// 核心代码:修改了版本号。这样当checkForComodification的时候,modCount值就和expectedModCount不同return true;}}} else {for (int i = 0; i < s; i++) {if (a[i] == null) {System.arraycopy(a, i + 1, a, i, --s - i);a[s] = null; // Prevent memory leaksize = s;modCount++;return true;}}}return false;}

接下来梳理一下流程,这时候你就会发现这个异常是在next方法的checkForComodification中抛出的。抛出的原因是
modCount !=expectedModCount。这里的modCount是指这个list对象从呢我出来到现在被修改的次数,当调用list
的add或者remove方法的时候,这个modCount都会自动增减;iterator创建的时候modCount被复制给了
expectedModcount,但是调用list的add和remove方法的时候不会同时自动增减expectedModcount,这样就导致
两个count不相等,从而抛出异常。大家如果理解了上面的执行流程,以后碰到类似这种问题,比如如果删除的是倒数
第二个元素却不会碰到异常。就会知道为什么了。

3、iterator遍历删除:

Iterator<String> it = list.iterator();while(it.hasNext()){String x = it.next();if(x.equals("del")){it.remove();}}

这种方式是可以正常遍历和删除的。但是你可能看到上面代码感觉和增强for循环内部实现的代码差不多,其实差别就在于上面使用
一个使用list.remove(),一个使用it.remove()。

(二)HashMap的遍历删除及如何实现遍历删除
一样我们先造一个hashmap出来,如下:

private static HashMap<Integer, String> map = new HashMap<Integer, String>();;public static void main(String[] args) {for(int i = 0; i < 10; i++){map.put(i, "value" + i);}}

1、第一种遍历删除:

for(Map.Entry<Integer, String> entry : map.entrySet()){Integer key = entry.getKey();if(key % 2 == 0){System.out.println("To delete key " + key);map.remove(key);System.out.println("The key " + + key + " was deleted");}

这种遍历删除依旧会报ConcurrentModificationException异常,
2、第二种遍历删除:
Set<Integer> keySet = map.keySet();for(Integer key : keySet){if(key % 2 == 0){System.out.println("To delete key " + key);keySet.remove(key);System.out.println("The key " + + key + " was deleted");}}

这种遍历删除依旧会报ConcurrentModificationException异常,
3、第三种遍历删除:
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();while(it.hasNext()){Map.Entry<Integer, String> entry = it.next();Integer key = entry.getKey();if(key % 2 == 0){ System.out.println("To delete key " + key); it.remove(); System.out.println("The key " + + key + " was deleted");}}

这种遍历是OK的
分析上述原因,如果大家理解了List的遍历删除,那么感觉HashMap的遍历删除是不是有类似之处啊。下面就分析一下原因:
如果查询源代码以上的三种的删除方式都是通过调用HashMap.removeEntryForKey方法来实现删除key的操作。
在removeEntryForKey方法内知识一场了key modCount就会执行一次自增操作,此时modCount就与expectedModCOunt不一致了
,上面三种remove实现中,只有第三种iterator的remove方法在调用完removeEntryForKey方法后同步了expectedModCount值与
modCount相同,所以iterator方式不会抛出异常。最后希望大家遇到问题到查询源代码,它会给你最好的解释!

热心网友 时间:2024-03-05 01:35

别看他们的一堆废话,直接记住我这个写法。以后就这么删除。

public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("abc", "aaa");
map.put("bac", "bbb");
map.put("1", "2");
System.out.println(map);
Iterator<String> iter = map.keySet().iterator();
while(iter.hasNext()){
String item = iter.next();
if(item.equals("bac")){
iter.remove();
}
}
System.out.println(map);
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
天通猫哪家好 211一本 城市规划专业的 今年大三 全部加权平均分81.5 只算专业课的... 什么叫头部券商 《重装机兵》那些经典的卖战车桥段,还记得帕特港买蓝色战车吗?_百度... 钢之季节情节简述 背部拉伤的症状 梦见大蜘蛛还有网啥含义 疫情期间隐瞒病情承担什么法律后果? 隐瞒疫情判几年啊 阻燃等级划分标准? java List类有什么功能 java中操作多个List java有哪些有序集合 JAVA里List的详细信息 java的List JAVA中的List的使用 java List 排名 用java找出这几个list,所有可能的组合,并且组合... 苹果 6plus刚换的新电池为什么充不进去电?我刚换... 苹果 6plus刚换的新电池为什么充不进去电?我刚换... 关于java List List[] 苹果6手机换了电池电充不进 苹果6手机换了电池电充不进 java list集合什么意思 苹果6电池换了充不进电 苹果6电池换了充不进电 在java的标准库中,请你找出哪些实现了list接口 java 除了arraylist 还有什么list 新换的iPhone 6电池,充不了电,怎么解决 苹果6充不进去电也不能开机,刚买的新电池,也没任... 如何修改QQ游戏上面认证的头像 qq头像v字认证怎么做 我要加V认证的qq头像 QQ游戏的认证头像怎样删除 带有腾讯认证图标的明星头像 qq头像怎样弄成官方认证? QQ拍拍的认证头像怎么搞? 谁有QQ认证头像,能发几张吗 怎么样在QQ头像弄V认证的图标 QQ资料验证那些头像我明明没有用过为什么验证还是... 为什么说不吃早餐反而会增肥? 不吃早餐会胖吗? 不吃早饭反而容易发胖,有什么依据吗? 科学表明不吃早餐容易发胖,这是为什么呢? 不吃早餐会发胖吗``? 不吃早餐真的会发胖吗? 经常不吃早餐,真的会变胖吗? 不吃早饭会变胖吗? 为什么说经常不吃早餐会导致肥胖?有根据吗? 不吃早餐反而会胖的原理?